/* =========================================================
   GLOBAL PAGE RULES
========================================================= */
:root { --void-bg: #000; --tv_center_y_offset: -72px; } /* ThreadVoid: default void background (overridden by moon phase) */
html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  touch-action: none;
  overscroll-behavior: none;
  background: var(--void-bg, #000);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
}

html { -webkit-text-size-adjust: 100%; }

/* =========================================================
   STAGE / VIEWPORT / WORLD WRAPPERS
========================================================= */
#stage {
  width: 100vw;
  height: 100vh;
  position: relative;
  overflow: hidden;
  background: var(--void-bg, #000);
}

#viewport {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

#world_anchor {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
  transform-origin: top left;
}

#world_scale {
  transform-origin: top left;
  will-change: transform;
}

#world_translate { position: relative; will-change: transform; }

#world {
  display: flex;
  flex-direction: column;
}

.row { display: flex; }

/* =========================================================
   TILE BASE STYLE
========================================================= */
:root {

  --tv_aura_idle: rgba(255,255,255,0.50);
  --tv_aura_busy: rgba(0, 255, 255, 0.85);
  --tv_aura_fx:   rgba(255, 170, 0, 0.90);
  --tv_aura_fail: rgba(255,  40, 40, 0.92);
--tv_aura_gain: rgba(120,255,80,0.90);
--tv_aura_pink: rgba(255,90,200,0.92);
--tv_aura_void: rgba(170,80,255,0.90);
--tv_aura_gold: rgba(200,150,60,0.92);

  --tv_ui_glow: var(--tv_aura_idle);
  --tv_ui_glow_size: 3px;

  --tv_btn_glow: var(--tv_aura_idle);
  --tv_btn_glow_size: 2px;
  --tv_frame_h: 28px;
}
.aura-idle { --tv_aura_ring: var(--tv_aura_idle); }
.aura-busy { --tv_aura_ring: var(--tv_aura_busy); }
.aura-fx   { --tv_aura_ring: var(--tv_aura_fx); }
.aura-fail { --tv_aura_ring: var(--tv_aura_fail); }
.aura-gain { --tv_aura_ring: var(--tv_aura_gain); }
.aura-pink { --tv_aura_ring: var(--tv_aura_pink); }
.aura-void { --tv_aura_ring: var(--tv_aura_void); }
.aura-gold { --tv_aura_ring: var(--tv_aura_gold); }
/* Data bubble aura wiring (extend existing) */
.data-bubble.aura-gain { --tv_aura_ring: var(--tv_aura_gain); --tv_aura_ring_size: 3px; }
.data-bubble.aura-pink { --tv_aura_ring: var(--tv_aura_pink); --tv_aura_ring_size: 3px; }
.data-bubble.aura-void { --tv_aura_ring: var(--tv_aura_void); --tv_aura_ring_size: 3px; }
.data-bubble.aura-gold { --tv_aura_ring: var(--tv_aura_gold); --tv_aura_ring_size: 3px; }
/* =========================================================
   THREAD KEYFRAMES (FIXED: NO MORE translate(-50%,-50%))
========================================================= */
@keyframes tv_thread_tilt_forward {
  0%   { transform: rotateX(0deg) translateY(0px)  scaleY(1); }
  50%  { transform: rotateX(-30deg) translateY(14px) scaleY(0.85); }
  100% { transform: rotateX(0deg) translateY(0px)  scaleY(1); }
}
@keyframes tv_thread_tilt_back {
  0%   { transform: rotateX(0deg) translateY(0px)  scaleY(1); }
  50%  { transform: rotateX(35deg) translateY(-14px) scaleY(0.85); }
  100% { transform: rotateX(0deg) translateY(0px)  scaleY(1); }
}
@keyframes tv_thread_spin_360 {
  0%   { transform: rotate(0deg); }
  25%  { transform: rotate(45deg); }
  75%  { transform: rotate(315deg); }
  100% { transform: rotate(360deg); }
}
@keyframes tv_thread_tilt_left {
  0%   { transform: rotate(0deg); }
  45%  { transform: rotate(-30deg); }
  100% { transform: rotate(0deg); }
}
@keyframes tv_thread_tilt_right {
  0%   { transform: rotate(0deg); }
  45%  { transform: rotate(30deg); }
  100% { transform: rotate(0deg); }
}

#thread_sprite.tv_tilt_forward,
#thread_sprite_stack.tv_tilt_forward { animation: tv_thread_tilt_forward 320ms ease-out 1; }
#thread_sprite.tv_tilt_back,
#thread_sprite_stack.tv_tilt_back    { animation: tv_thread_tilt_back    320ms ease-out 1; }
#thread_sprite.tv_tilt_left,
#thread_sprite_stack.tv_tilt_left    { animation: tv_thread_tilt_left    350ms ease-out 1; }
#thread_sprite.tv_tilt_right,
#thread_sprite_stack.tv_tilt_right   { animation: tv_thread_tilt_right   350ms ease-out 1; }
#thread_sprite.tv_spin_once,
#thread_sprite_stack.tv_spin_once    { animation: tv_thread_spin_360     700ms ease-in-out 1; }

.tile {
  display: flex;
  position: relative;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;

  border: 1px solid #111;
  border:none;
  border-radius: 0px;
  background-color: #111;
  color: rgba(255,255,255,0.55);
  font-size: 12px;
  line-height: 1.1;
  text-align: center;

  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;

  width: var(--tile);
  height: var(--tile);
  background-size: var(--tile) var(--tile);
  background-repeat: no-repeat;
  image-rendering: pixelated;
}

/* =========================================================
   TILE LAYERS (subAtlas / atlas / thingAtlas / frameAtlas / fxAtlas)
   - Each layer is a full-tile pixel canvas (CSS background-image).
   - We control z-order with z-index, without changing tile sizing.
========================================================= */
.tile-layer{
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: var(--tile) var(--tile);
  background-repeat: no-repeat;
  background-position: center;
  image-rendering: pixelated;
  transform: rotate(var(--tv-layer-rot, 0deg));
  transform-origin: 50% 50%;
}
.tile-sub{   z-index: 1; }
.tile-main{  z-index: 2; }
.tile-thing{ z-index: 3; }
.tile-frame{ z-index: 4; }
.tile-fx{    z-index: 5; }

/* Debug text (only filled when DEBUG=true) */
.tile-debug{
  position: relative;
  z-index: 4;
  pointer-events: none;
}

/* Stronger touch kill-switch across the world tree */
#stage, #viewport, #world, #world * { touch-action: none; }

/* =========================================================
   THREAD POSITION HIGHLIGHT (center tile)
========================================================= */
.tile.thread-here{
  outline: 2px solid 222;
  outline-offset: -2px;
  z-index: 999;
  position: relative;
}

/* =========================================================
   THREAD OVERLAY (always centered on screen)
========================================================= */
#thread_layer {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 9000;
  pointer-events: none;
  perspective: 500px;
  perspective-origin: 50% 50%;
  --tv_thread_scale: 1;
}

/* NEW: wrapper owns centering (translate only, no scale) */
#thread_wrap {
  position: absolute;
  left: 50%;
  top: calc(50% + var(--tv_center_y_offset, 0px));
  transform: translate(-50%, -50%) rotate(var(--tv_thread_base_rot, 0deg)) scale(var(--tv_thread_scale, 1));
  transform-origin: 50% 50%;
  pointer-events: none;
}
/* UPDATED: sprite no longer centers itself. it just animates/scales */
#thread_sprite {
  transform-origin: 50% 50%;
  position: absolute;
  left: 0;
  top: 0;


  --tv_aura_ring_size: 1px;

  background: transparent;
  border-radius: 23px;
  box-shadow:
    0 0 8px 8px rgba(20,20,20,0.95),
    inset 0 0 var(--tv_aura_ring_size) var(--tv_aura_ring_size) var(--tv_aura_ring, rgba(255,255,255,0.5)),
    inset 0 0 5px 5px rgba(120,120,120,0.95);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
  image-rendering: pixelated;
  transition: box-shadow 140ms ease;

  transform-style: preserve-3d;
  backface-visibility: hidden;

  /* keep your hinge */
  transform-origin: 50% 65%;
}

/* Layered thread renderer:
   - #thread_sprite_stack owns the old sprite shell/aura/motion contract.
   - The child thread layers are image-only. They must never inherit the shell glow,
     because then the aura gets trapped inside a layer box like CSS has developed opinions. */
#thread_sprite_stack {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  --tv_aura_ring_size: 1px;
  --tv_aura_ring: var(--tv_aura_idle);
  background: transparent;
  border-radius: 23px;
  box-shadow: none;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
  image-rendering: pixelated;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  transform-origin: 50% 65%;
  pointer-events: none;
  overflow: visible;
  isolation: isolate;
}

/* Aura shell sits above the composed sprite stack, not on any atlas layer. */
#thread_sprite_stack::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  border-radius: 23px;
  box-shadow:
    0 0 8px 8px rgba(20,20,20,0.95),
    inset 0 0 var(--tv_aura_ring_size) var(--tv_aura_ring_size) var(--tv_aura_ring, rgba(255,255,255,0.5)),
    inset 0 0 5px 5px rgba(120,120,120,0.95);
  transition: box-shadow 140ms ease;
}

#thread_sprite_stack .thread-layer,
#thread_wrap > .thread-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center;
  image-rendering: pixelated;
  transform-origin: 50% 50%;
  box-shadow: none !important;
  border-radius: 0 !important;
}

#thread_sprite_stack .thread-sub{ z-index: 1; }
#thread_sprite_stack .thread-main{ z-index: 2; }
#thread_sprite_stack .thread-thing{ z-index: 3; }
#thread_sprite_stack .thread-frame{ z-index: 4; }
#thread_sprite_stack .thread-fx{ z-index: 5; }

/* =========================================================
   THREAD AURA STATES
========================================================= */
#thread_sprite.aura-idle,
#thread_sprite_stack.aura-idle { --tv_aura_ring: var(--tv_aura_idle); --tv_aura_ring_size: 1px; }
#thread_sprite.aura-busy,
#thread_sprite_stack.aura-busy { --tv_aura_ring: var(--tv_aura_busy); --tv_aura_ring_size: 3px; }
#thread_sprite.aura-fx,
#thread_sprite_stack.aura-fx   { --tv_aura_ring: var(--tv_aura_fx);   --tv_aura_ring_size: 3px; }
#thread_sprite.aura-fail,
#thread_sprite_stack.aura-fail { --tv_aura_ring: var(--tv_aura_fail); --tv_aura_ring_size: 3px; }
#thread_sprite.aura-gain,
#thread_sprite_stack.aura-gain { --tv_aura_ring: var(--tv_aura_gain); --tv_aura_ring_size: 3px; }
#thread_sprite.aura-pink,
#thread_sprite_stack.aura-pink { --tv_aura_ring: var(--tv_aura_pink); --tv_aura_ring_size: 3px; }
#thread_sprite.aura-void,
#thread_sprite_stack.aura-void { --tv_aura_ring: var(--tv_aura_void); --tv_aura_ring_size: 3px; }
#thread_sprite.aura-gold,
#thread_sprite_stack.aura-gold { --tv_aura_ring: var(--tv_aura_gold); --tv_aura_ring_size: 3px; }

/* keep fill-mode behavior */
#thread_sprite.tv_tilt_forward,
#thread_sprite.tv_tilt_back,
#thread_sprite.tv_tilt_left,
#thread_sprite.tv_tilt_right,
#thread_sprite.tv_spin_once,
#thread_sprite_stack.tv_tilt_forward,
#thread_sprite_stack.tv_tilt_back,
#thread_sprite_stack.tv_tilt_left,
#thread_sprite_stack.tv_tilt_right,
#thread_sprite_stack.tv_spin_once {
  animation-fill-mode: both;
}

/* =========================================================
   UI BASE STYLES
========================================================= */
.ui {
  position: fixed;
  
  z-index: 9999;
  pointer-events: auto;
  background: rgba(0,0,0,0.95);
  color: #ddd;
  border: 2px solid rgba(34,34,34,1);
  box-shadow:
    0 0 4px 4px rgba(17,17,17,0.9),
    0 0 var(--tv_ui_glow_size) var(--tv_ui_glow_size) var(--tv_ui_glow);
  padding: 10px;
  border-radius: 12px;

  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

:root { --actions-ui-offset: 517px; }

.nav-ui {
  left: 25px;
  right: 25px;
  bottom: calc(10px + var(--actions-ui-offset, 200px)+ var(--tv_frame_h, 0px));
}

.actions-ui {
  left: 25px;
  right: 25px;
  bottom: calc(10px + var(--tv_frame_h, 0px));
}

.ui h2 {
  text-align:center;
  margin:0;
  font-size:1.2em;
  border-bottom:2px solid #ccc;
  padding-bottom:3px;
  margin-bottom:5px;
}

.ui-mode-line {
  text-align: center;
  margin: -2px 0 8px 0;
  font-size: 11px;
  line-height: 1.2;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: rgba(221,221,221,0.72);
  text-shadow: 0 1px 0 rgba(0,0,0,0.9);
  pointer-events: none;
}

.ui-mode-line::before {
  content: "mode: ";
  opacity: 0.55;
}

.ui.aura-idle { --tv_ui_glow: var(--tv_aura_idle); --tv_ui_glow_size: 3px; }
.ui.aura-busy { --tv_ui_glow: var(--tv_aura_busy); --tv_ui_glow_size: 6px; }
.ui.aura-fx   { --tv_ui_glow: var(--tv_aura_fx);   --tv_ui_glow_size: 6px; }
.ui.aura-fail { --tv_ui_glow: var(--tv_aura_fail); --tv_ui_glow_size: 6px; }
.ui.aura-gain { --tv_ui_glow: var(--tv_aura_gain); --tv_ui_glow_size: 6px; }
.ui.aura-pink { --tv_ui_glow: var(--tv_aura_pink); --tv_ui_glow_size: 6px; }
.ui.aura-void { --tv_ui_glow: var(--tv_aura_void); --tv_ui_glow_size: 6px; }
.ui.aura-gold { --tv_ui_glow: var(--tv_aura_gold); --tv_ui_glow_size: 6px; }
/* =========================================================
   PANEL UI SHELLS
   Smaller screens are cruel little rectangles, so modal panels
   now live above the nav area and scroll internally.
========================================================= */
.panel-ui {
  left: 25px;
  right: 25px;
  top: calc(env(safe-area-inset-top, 0px) + 74px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 46px);
  min-height: 0;
  max-height: none;
  padding-bottom: 15px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 22000;
}

.panel-ui-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  padding-right: 6px;
}

.panel-ui-footer {
  padding: 18px 8px 6px 8px;
}

.panel-close-btn {
  max-width: 320px;
  margin: 0 auto;
}

body.tv-panel-open #ui_slotbar_primary,
body.tv-panel-open #ui_slotbar_secondary,
#ui_slotbar_primary.is-hidden-by-panel,
#ui_slotbar_secondary.is-hidden-by-panel {
  display: none !important;
}

/* =========================================================
   Drive UI PANEL
========================================================= */
.drive-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.drive-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.drive-ui-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  padding-right: 6px;
}


/* =========================================================
   VOIDBOX UI PANEL
========================================================= */
.voidBox-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.voidBox-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.voidBox-ui-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  padding-right: 6px;
}

#voidBoxText {
  color: #444444;
  padding: 3px;
  border: 1px solid #222222;
}
/* =========================================================
   DIVE UI PANEL
========================================================= */
.dive-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.dive-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.dive-ui-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  padding-right: 6px;
}

/* =========================================================
   DIVE: TILE META (readable + mobile friendly)
========================================================= */
.dive-tile-meta{
  margin-top: 10px;
  padding: 10px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.45);
  color: #ddd;
}

.dive-meta-head{
  display: grid;
  gap: 2px;
  margin-bottom: 8px;
}
.dive-meta-title{
  font-weight: 900;
  font-size: 16px;
  line-height: 1.2;
  text-align: center;
  word-break: break-word;
}
.dive-meta-sub{
  font-size: 13px;
  opacity: 0.9;
  text-align: center;
  letter-spacing: 0.3px;
}

.dive-chips{
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin: 6px 0 10px 0;
}
.dive-chip{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 8px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.14);
  background: rgba(0,0,0,0.35);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.2px;
}

/* tint chips using your aura palette (text only, subtle) */
.dive-chip.aura-idle{ color: var(--tv_aura_idle); }
.dive-chip.aura-busy{ color: var(--tv_aura_busy); }
.dive-chip.aura-fx{   color: var(--tv_aura_fx); }
.dive-chip.aura-fail{ color: var(--tv_aura_fail); }
.dive-chip.aura-gain{ color: var(--tv_aura_gain); }
.dive-chip.aura-pink{ color: var(--tv_aura_pink); }
.dive-chip.aura-void{ color: var(--tv_aura_void); }
.dive-chip.aura-gold{ color: var(--tv_aura_gold); }

.dive-meta-grid{
  display: grid;
  gap: 6px;
}
.dive-kv{
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 10px;
  padding: 4px 0;
  border-bottom: 1px dashed rgba(255,255,255,0.10);
}
.dive-kv:last-child{ border-bottom: none; }

.dive-k{
  opacity: 0.8;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-size: 12px;
}
.dive-v{
  font-size: 14px;
  line-height: 1.25;
  word-break: break-word;
}

.dust-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.dust-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
/* DUST LIST: allow vertical scrolling even though items are ui-btn */
#dust_script_list .ui-btn,
#dust_script_list .ui_btn_generated {
  touch-action: pan-y !important;
}
#dust_script_list {
  display: grid;
  gap: 8px;
  padding-left:10px;
  padding-right:10px;
  margin-top: 14px;
  max-height: min(36vh, 320px);          /* or calc(100vh - <header+footer px>) */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
flex: 1 1 auto;
  overflow-y: auto;
}

.dust-selected {
  margin-top: 6px;
  padding: 6px 8px;
  font-family: monospace;
  border: 2px solid #222;
  border-radius: 10px;
}

/* UI grid layout */
.ui-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 8px;
}
.ui-row:last-child { margin-bottom: 0; }

/* UI button base */
.ui-btn {
  height: 52px;
  border-radius: 10px;
  border: 1px solid #333;
  /* background: 111; */ /* intentionally broken: kept as reference */
  color: #ddd;

  font-size: 16px;
  font-weight: 700;

  display: flex;
  align-items: center;
  justify-content: center;

  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

.ui-btn:active { background: #1a1a1a; }
.ui-btn.disabled { opacity: 0.4; }

.ui-btn{
  box-shadow:
    0 0 2px 2px rgba(0,0,0,0.6),
    0 0 var(--tv_btn_glow_size) var(--tv_btn_glow_size) var(--tv_btn_glow);
}

.ui-btn.aura-idle { --tv_btn_glow: var(--tv_aura_idle); --tv_btn_glow_size: 2px; }
.ui-btn.aura-busy { --tv_btn_glow: var(--tv_aura_busy); --tv_btn_glow_size: 4px; }
.ui-btn.aura-fx   { --tv_btn_glow: var(--tv_aura_fx);   --tv_btn_glow_size: 4px; }
.ui-btn.aura-fail { --tv_btn_glow: var(--tv_aura_fail); --tv_btn_glow_size: 4px; }
.ui-btn.aura-gain { --tv_btn_glow: var(--tv_aura_gain); --tv_btn_glow_size: 4px; }
.ui-btn.aura-pink { --tv_btn_glow: var(--tv_aura_pink); --tv_btn_glow_size: 4px; }
.ui-btn.aura-void { --tv_btn_glow: var(--tv_aura_void); --tv_btn_glow_size: 4px; }
.ui-btn.aura-gold { --tv_btn_glow: var(--tv_aura_gold); --tv_btn_glow_size: 4px; }

.dive-tile-preview{
  width: 96px;
  height: 96px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  border-radius: 8px;
  display: inline-block;
}

/* =========================================================
   INPUT UI (Tile-Glyph Typing)
========================================================= */
.buffer-ui{
  /* IMPORTANT (especially iOS):
     prevent the outer container from being a scroll container.
     Let the inner panes (.buffer-marks / .buffer-string) handle scrolling.
     Nested scroll containers often feel "dead" on mobile Safari. */
  overflow: hidden;
  -webkit-overflow-scrolling: auto;
  touch-action: pan-y !important;

  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}

/* Ensure Buffer UI sub-elements are allowed to scroll even with global
   touch-kill rules used for the game world. */
.buffer-ui,
.buffer-ui *{
  touch-action: pan-y !important;
}
.buffer-ui.is-open{
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

/* Buffer UI: internal section headings */
.buffer-section{
  margin-top: 6px;
}
.buffer-section-title{
  margin: 2px 2px 6px 2px;
  font-size: 14px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  opacity: 0.85;
}
.buffer-section-buffer{
  margin-top: 10px;
}


.buffer-string{
  margin-top: 6px;
  padding: 8px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: 18px;
  line-height: 1.35;
  word-break: break-word;
  border: 2px solid #222;
  border-radius: 10px;
  color: #ddd;
  background: rgba(10,10,10,0.6);
  max-height: 220px;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
}




/* =========================================================
   BUFFER: MARKS LIST (shown above raw buffer string)
   - Uses global .aura-* colors (unified palette)
========================================================= */
.buffer-marks{
  margin-top: 6px;
  margin-bottom: 8px;
  padding: 8px 10px;
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.45);
  max-height: 140px;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
}

.buffer-marks-empty{
  opacity: 0.75;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: 14px;
}
.buffer-mark-row{
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 2px 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: 14px;
  line-height: 1.25;
  border-bottom: 1px dashed rgba(255,255,255,0.10);
}
.buffer-mark-row:last-child{ border-bottom: none; }
.buffer-mark-aura{
  min-width: 52px;
  text-transform: lowercase;
  letter-spacing: 0.5px;
  opacity: 0.95;
}

/* Color the aura label text using the unified aura palette */
.buffer-mark-aura.aura-idle{ color: var(--tv_aura_idle); }
.buffer-mark-aura.aura-busy{ color: var(--tv_aura_busy); }
.buffer-mark-aura.aura-fx{ color: var(--tv_aura_fx); }
.buffer-mark-aura.aura-void{ color: var(--tv_aura_void); }
.buffer-mark-aura.aura-fail{ color: var(--tv_aura_fail); }
.buffer-mark-aura.aura-gain{ color: var(--tv_aura_gain); }
.buffer-mark-aura.aura-pink{ color: var(--tv_aura_pink); }
.buffer-mark-aura.aura-gold{ color: var(--tv_aura_gold); }

.buffer-mark-key{
  color: #ddd;
  word-break: break-all;
}
/* =========================================================
   LORE TOAST (Name + Lore line)
========================================================= */
:root { --tv_lore_color: #9f9f9fff; }

.tv-lore-toast {
  position: fixed;
  left: 50%;
  top: 190px;
  transform: translateX(-50%) translateY(-40px);
  z-index: 10050;
  pointer-events: none;
  width: 80%;
  color: var(--tv_lore_color);
  background: rgba(1,1,1,1.35);
  border: 2px solid #222;
  border-radius: 12px;
  padding: 10px 14px;

  box-shadow:
    0 0 3px 3px rgba(90, 90, 90, 0.58),
    0 0 55px 55px #000000ff,
    inset 0 0 20px 120px rgba(0, 0, 0, 0.9);

  opacity: 0;
  transition: opacity 920ms ease, transform 600ms ease;
}

.tv-lore-toast.is-open {
  opacity: 1;
  transform: translateX(-50%) translateY(0px);
}

.tv-lore-name {
  font-weight: 800;
  font-size: 18px;
  line-height: 1.3;
  text-align: center;
  text-shadow: 0 2px 2px rgba(2,2,2,0.9);
  padding-left: 25px;
  padding-right: 25px;
 padding-top:15px;
}

.tv-lore-line {
  margin-top: 4px;
  font-size: 15px;
  line-height: 1.5;
  text-align: center;
  opacity: 0.95;
  text-shadow: 0 2px 2px rgba(2,2,2,0.9);
  padding-left: 50px;
  padding-right: 50px;
  padding-bottom:15px;
}

/* =========================================================
   INPUT NUCLEAR OVERRIDE
========================================================= */
.nuke-input,
.nuke-input *,
.nuke-input *::before,
.nuke-input *::after {
  touch-action: none !important;
  -ms-touch-action: none !important;

  user-select: none !important;
  -webkit-user-select: none !important;
  -moz-user-select: none !important;
  -ms-user-select: none !important;

  -webkit-touch-callout: none !important;
  -webkit-tap-highlight-color: transparent !important;

  -webkit-text-size-adjust: 100% !important;
}

.nuke-input a,
.nuke-input button,
.nuke-input input,
.nuke-input textarea {
  outline: none !important;
  appearance: none !important;
  -webkit-appearance: none !important;
}

/* Buffer UI must remain scrollable even when input is nuked.
   We want to block world panning, not UI scrolling. */
.nuke-input .buffer-ui,
.nuke-input .buffer-ui *{
  touch-action: pan-y !important;
  -ms-touch-action: pan-y !important;
}
.nuke-input .buffer-marks,
.nuke-input .buffer-string{
  overflow-y: auto !important;
  -webkit-overflow-scrolling: touch;
}

/* Generated buttons reuse your existing .nav_btn style if it exists.
   This is just a fallback so they don’t render like sad default buttons. */
.ui_btn_generated {
  min-height: 44px;
}
/* =========================================================
   WINDOW AURA (full-screen inset glow)
   - sits above #stage but below .ui panels
   - does NOT affect layout like borders do
========================================================= */
#uiShell{
  position: fixed;
  inset: 0;
  top: var(--tv_frame_h) !important;
  bottom: var(--tv_frame_h) !important;
  z-index: 9500;          /* .ui is 9999, lore toast is higher */
  pointer-events: none;
  --tv_window_glow: var(--tv_aura_fail);
  --tv_window_glow_size:2px;
}

#uiShell::before{
  content:"";
  position:absolute;
  inset: 0;
  /* inset window aura */
  box-shadow:
    inset 0 0 var(--tv_window_glow_size) var(--tv_window_glow_size) var(--tv_window_glow),
    inset 0 0 120px 40px rgba(0,0,0,0.55); /* optional: adds depth */
}

/* re-use the same aura state names */
#uiShell.aura-idle { --tv_window_glow: var(--tv_aura_idle); --tv_window_glow_size: 14px; }
#uiShell.aura-busy { --tv_window_glow: var(--tv_aura_busy); --tv_window_glow_size: 22px; }
#uiShell.aura-fx   { --tv_window_glow: var(--tv_aura_fx);   --tv_window_glow_size: 22px; }
#uiShell.aura-fail { --tv_window_glow: var(--tv_aura_fail); --tv_window_glow_size: 24px; }
#uiShell.aura-gain { --tv_window_glow: var(--tv_aura_gain); --tv_window_glow_size: 22px; }
#uiShell.aura-pink { --tv_window_glow: var(--tv_aura_pink); --tv_window_glow_size: 22px; }
#uiShell.aura-void { --tv_window_glow: var(--tv_aura_void); --tv_window_glow_size: 22px; }
#uiShell.aura-gold { --tv_window_glow: var(--tv_aura_gold); --tv_window_glow_size: 22px; }

#topFrame,
#bottomFrame{
  position: fixed;
  left: 0;
  right: 0;
  height: 28px;
  padding-top:3px;
  background: var(--void-bg, #000);
  z-index: 10000;
  color: #ddd;
  text-align:center;
}

#topFrame{ top: 0; }
#bottomFrame{ bottom: 0; }
#ui_slotbar_primary{ bottom: calc(20px + var(--tv_frame_h, 0px)) !important; }
/* =========================
   DATA BUBBLES (Top HUD)
========================= */

.data-bubbles-shell{
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 70px);
  left: 20px;
  right: 20px;
  z-index: 80; /* above world, below toasts if needed */
  display: flex;
  flex-wrap: wrap;          /* ← THIS */
  justify-content: center;
  align-items: center; 
  gap: 10px;

  /* shell itself is invisible */
  background: transparent;
  border: 0;
  pointer-events: none; /* bubbles are display-only for now */
}

.data-bubble{
  width: 38px;
  height: 38px;
  overflow:hidden;
  padding: 0 2px;
  display: flex;
flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 12px;

  /* thread-like capsule feel */
  background: rgba(0,0,0,0.65);
box-shadow:
    0 0 3px 3px rgba(20,20,20,0.95),
    inset 0 0 var(--tv_aura_ring_size) var(--tv_aura_ring_size) var(--tv_aura_ring, rgba(255,255,255,0.5)),
    inset 0 0 4px 4px rgba(120,120,120,0.95);

  /* text */
  color: rgba(240,240,240,0.92);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 10px;
  letter-spacing: 0.5px;
  text-shadow: 0 1px 0 rgba(0,0,0,0.7);

  /* allow aura classes to glow it */
  will-change: filter, box-shadow, transform;
}

/* show/hide mechanic */
.data-bubble.is-hidden{
  display: none;
}

.data-bubble-value{
  display: inline-block;
  max-width: 5ch;
  overflow: hidden;
  text-overflow: clip;
  white-space: nowrap;
}
/* Data bubble aura wiring (match your UI/Thread aura system) */
.data-bubble{
  --tv_aura_ring: var(--tv_aura_idle);
  --tv_aura_ring_size: 1px;
}

.data-bubble.aura-idle { --tv_aura_ring: var(--tv_aura_idle); --tv_aura_ring_size: 1px; }
.data-bubble.aura-busy { --tv_aura_ring: var(--tv_aura_busy); --tv_aura_ring_size: 3px; }
.data-bubble.aura-fx   { --tv_aura_ring: var(--tv_aura_fx);   --tv_aura_ring_size: 3px; }
.data-bubble.aura-fail { --tv_aura_ring: var(--tv_aura_fail); --tv_aura_ring_size: 3px; }



/* =========================
   ORB FX (floating reward text)
   - purely visual, sits near the centered thread
========================= */
#orb_fx_layer{
  position: fixed;
  inset: 0;
  z-index: 9050;        /* above world + thread sprite, below uiShell/ui */
  pointer-events: none;
}

.tv-orb{
  position: absolute;
  left: 50%;
  top: calc(50% + var(--tv_center_y_offset, 0px));
  transform: translate(-50%,-50%);

  /* DO NOT CHANGE SIZE (kept identical) */
  min-width: 26px;
  height: 26px;
  padding: 0 8px;
  border-radius: 14px;

  display: inline-flex;
  align-items: center;
  justify-content: center;

  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.2px;
  color: rgba(245,245,245,0.95);
  text-shadow: 0 1px 0 rgba(0,0,0,0.75);

  /* Aura-ring vars (same pattern as #thread_sprite) */
  --tv_aura_ring: rgba(255,255,255,0.50);
  --tv_aura_ring_size: 1px;

  /* Match thread + bubble aura styling (NO new look) */
  background: rgba(0,0,0,0.15);
  box-shadow:
    0 0 8px 8px rgba(20,20,20,0.95),
    inset 0 0 var(--tv_aura_ring_size) var(--tv_aura_ring_size) var(--tv_aura_ring, rgba(255,255,255,0.5)),
    inset 0 0 5px 5px rgba(120,120,120,0.95);

  /* Kill the washed-out glow method */
  filter: none;

  opacity: 0;
  will-change: transform, opacity;
}

@keyframes tv_orb_float_up {
  0%   { opacity: 0; transform: translate(-50%,-50%) translate(var(--ox,0px), var(--oy,0px)) scale(0.90); }
  10%  { opacity: 1; }
  95%  { opacity: 0.95; }
  100% { opacity: 0; transform: translate(-50%,-50%) translate(var(--ox,0px), calc(var(--oy,0px) - 80px)) scale(1.05); }
}

.tv-orb.is-float{
  animation: tv_orb_float_up 800ms ease-out 1;
}

/* Aura states: exact same values as your thread aura states */
.tv-orb.aura-idle { --tv_aura_ring: rgba(255,255,255,0.50); --tv_aura_ring_size: 1px; }
.tv-orb.aura-busy { --tv_aura_ring: rgba(0, 255, 255, 0.85); --tv_aura_ring_size: 3px; }
.tv-orb.aura-fx   { --tv_aura_ring: rgba(255, 170, 0, 0.90); --tv_aura_ring_size: 3px; }
.tv-orb.aura-fail { --tv_aura_ring: rgba(255,  40, 40, 0.92); --tv_aura_ring_size: 3px; }
/* ORB aura routing (match bubbles + thread) */
.tv-orb.aura-gain { --tv_aura_ring: var(--tv_aura_gain); --tv_aura_ring_size: 3px; }
.tv-orb.aura-pink { --tv_aura_ring: var(--tv_aura_pink); --tv_aura_ring_size: 3px; }
.tv-orb.aura-void { --tv_aura_ring: var(--tv_aura_void); --tv_aura_ring_size: 3px; }
.tv-orb.aura-gold { --tv_aura_ring: var(--tv_aura_gold); --tv_aura_ring_size: 3px; }

.data-bubbles-shell{ pointer-events: auto !important; }
.data-bubble{ pointer-events: auto !important; }


/* =========================================================
   DATA UI (Bubble Manager) - same feel as DUST list
========================================================= */
.data-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.data-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.auth-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.auth-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.intro-ui {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 160ms ease, transform 160ms ease;
}

.intro-ui.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.intro-ui-body,
.auth-ui-body,
.dust-ui-body,
.data-ui-body,
.buffer-ui-body,
.drive-ui-body,
.dive-ui-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  padding-right: 6px;
}

/* Scroll list exactly like DUST */
#data_bubble_list {
  display: grid;
  gap: 8px;
  padding-left: 15px;
  padding-right: 15px;
  margin-top: 14px;
  max-height: min(36vh, 320px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y !important;
  flex: 1 1 auto;
}

/* Allow vertical scroll even though items are ui-btn */
#data_bubble_list .ui-btn,
#data_bubble_list .ui_btn_generated {
  touch-action: pan-y !important;
}

/* Allow inner content regions to scroll even with world touch lock */
.panel-ui-body,
.panel-ui-body *,
.dive-ui-body,
.dive-ui-body *,
.intro-ui-body,
.intro-ui-body *,
.drive-ui-body,
.drive-ui-body * {
  touch-action: pan-y !important;
}



/* ============================================================
   TILE MARKING (overlay)
   - Pure ::after overlay, does NOT change tile sizing/borders.
   - Uses existing aura palette variables:
     --tv_aura_busy, --tv_aura_idle, --tv_aura_fx, --tv_aura_fail,
     --tv_aura_gain, --tv_aura_pink, --tv_aura_void, --tv_aura_gold
   ============================================================ */

.tile.tv-mark::after{
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: 0px;
z-index: 420; /* sit above sub/main/frame/fx 
  /* default ring */
  --tv_mark_ring: var(--tv_aura_busy);
  --tv_mark_ring_size: 3px;
  box-shadow:
    inset 0 0 0 var(--tv_mark_ring_size) var(--tv_mark_ring),
    inset 0 0 10px var(--tv_mark_ring);
}

/* Color variants */
.tile.tv-mark-busy::after{ --tv_mark_ring: var(--tv_aura_busy); }
.tile.tv-mark-idle::after{ --tv_mark_ring: var(--tv_aura_idle); }
.tile.tv-mark-fx::after{   --tv_mark_ring: var(--tv_aura_fx); }
.tile.tv-mark-fail::after{ --tv_mark_ring: var(--tv_aura_fail); }
.tile.tv-mark-gain::after{ --tv_mark_ring: var(--tv_aura_gain); }
.tile.tv-mark-pink::after{ --tv_mark_ring: var(--tv_aura_pink); }
.tile.tv-mark-void::after{ --tv_mark_ring: var(--tv_aura_void); }
.tile.tv-mark-gold::after{ --tv_mark_ring: var(--tv_aura_gold); }


/* =========================================================
   GUIDE OVERLAY (Pixel Forge / reference image)
========================================================= */
#guide_layer{
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  overflow: visible;
  pointer-events: none;
  z-index: 999;
  display: none;
}
#guide_layer img{
  position: absolute;
  left: 0;
  top: 0;
  display: none;
  max-width: none;
  max-height: none;
  transform-origin: top left;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  image-rendering: auto;
  opacity: 0.45;
}
#guide_layer.is-visible img{
  display: block;
}


/* Dive preview tile stack */
.dive-tile-preview{
  position: relative;
  overflow: hidden;
  background-color: #111;
  background-image: none;
  image-rendering: pixelated;
}
.dive-tile-preview .tile-layer{
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center;
  image-rendering: pixelated;
  transform: rotate(var(--tv-layer-rot, 0deg));
  transform-origin: 50% 50%;
}
.dive-tile-preview .tile-sub{ z-index: 1; }
.dive-tile-preview .tile-main{ z-index: 2; }
.dive-tile-preview .tile-thing{ z-index: 3; }
.dive-tile-preview .tile-frame{ z-index: 4; }
.dive-tile-preview .tile-fx{ z-index: 5; }


@media (max-height: 760px) {
  .panel-ui {
    left: 14px;
    right: 14px;
    top: calc(env(safe-area-inset-top, 0px) + 58px);
    bottom: calc(env(safe-area-inset-bottom, 0px) + 34px);
  }

  .ui h2 {
    font-size: 1.05em;
  }

  .ui-mode-line {
    font-size: 10px;
    margin-bottom: 6px;
  }
}

/* =========================================================
   HUD MESSAGE TOASTS
   - Supports title/context line + multiline body text.
========================================================= */
#tv_hud {
  position: fixed;
  left: 50%;
  top: calc(env(safe-area-inset-top, 0px) + 45px);
  transform: translateX(-50%);
  z-index: 12000;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  pointer-events: none;
  width: min(92vw, 760px);
}

#tv_hud_message {
  display: none;
  min-width: 210px;
  max-width: min(80%, 680px);
  box-sizing: border-box;
  padding: 8px 14px 12px 14px;
  border-radius: 14px;
  background: rgba(48, 48, 48, 0.42);
  border: 2px solid rgba(255, 255, 255, 0.53);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  color: #d4d2d2;
  font-size: 15px;
  line-height: 1.45;
  text-align: center;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  white-space: normal;
  overflow-wrap: anywhere;
}

#tv_hud_message.is-visible { display: block; }

.tv-hud-title {
  display: block;
  margin: 0 0 5px 0;
  color: rgba(212, 210, 210, 0.72);
  font-size: 10px;
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(0,0,0,0.95);
}

.tv-hud-body {
  display: block;
  color: rgba(235, 235, 235, 0.94);
  font-size: 15px;
  line-height: 1.45;
  white-space: pre-line;
  text-shadow: 0 1px 0 rgba(0,0,0,0.95);
}

#tv_hud_message.type-info { border-color: rgba(101, 183, 254, 0.75); }
#tv_hud_message.type-warning { border-color: rgba(252, 161, 14, 0.81); }
#tv_hud_message.type-fail,
#tv_hud_message.type-error { border-color: rgba(240, 5, 5, 0.71); }
#tv_hud_message.type-void { border-color: rgba(170, 80, 255, 0.75); }

#tv_hud_status {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

.tv-hud-pill {
  display: none;
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(12, 16, 28, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #dfe7ff;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.24);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.tv-hud-pill.is-visible {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 420px) {
  #tv_hud {
    left: 12px;
    right: 12px;
    width: auto;
    transform: none;
  }

  #tv_hud_message {
    max-width: 100%;
    min-width: min(210px, 100%);
  }
}

/* =========================================================
   DATA UI REFINEMENT PASS (v32)
   Keeps the newer Data UI layout while restoring legacy bubble/orb styling.
========================================================= */
.data-panel-intro{
  margin: 4px 6px 10px 6px;
  padding: 8px 10px;
  font-size: 13px;
  line-height: 1.35;
  text-align: center;
  color: rgba(221,221,221,0.82);
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.45);
}

.data-summary-card{
  margin: 8px 6px 10px 6px;
  padding: 9px 10px;
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.55);
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
}

.data-summary-title{
  font-size: 15px;
  line-height: 1.25;
  font-weight: 900;
  text-align: center;
}

.data-summary-meta{
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.25;
  opacity: 0.78;
  text-align: center;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

#data_bubble_list{
  gap: 8px;
  padding-left: 6px;
  padding-right: 6px;
  margin-top: 8px;
  max-height: none;
}

.data-controls-grid{
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}

.data-action-btn{
  min-height: 44px;
  height: 46px;
  font-size: 14px;
  border-radius: 10px;
}

.data-bubble-rows{
  display: grid;
  gap: 7px;
}

.data-bubble-row{
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.48);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.04);
  touch-action: pan-y !important;
}

.data-bubble-row.is-shown{
  border-color: rgba(255,255,255,0.20);
}

.data-bubble-row.is-hidden-row{
  opacity: 0.56;
}

.data-bubble-row-left,
.data-bubble-row-right{
  min-width: 0;
}

.data-bubble-row-name{
  font-size: 15px;
  font-weight: 900;
  line-height: 1.15;
  word-break: break-word;
}

.data-bubble-row-key{
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.1;
  opacity: 0.62;
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.data-bubble-row-right{
  text-align: right;
}

.data-bubble-row-value{
  font-size: 16px;
  font-weight: 900;
  line-height: 1.1;
}

.data-bubble-row-state{
  margin-top: 2px;
  font-size: 10px;
  line-height: 1.1;
  opacity: 0.7;
  text-transform: uppercase;
  letter-spacing: 0.7px;
}

/* Fix old comment bleed in tile marks, because apparently CSS also enjoys cave collapses. */
.tile.tv-mark::after{
  z-index: 420;
}

@media (max-width: 420px){
  .data-bubbles-shell{
    left: 10px;
    right: 10px;
    gap: 6px;
  }
  .data-bubble{
    width: 32px;
    height: 32px;
    min-width: 32px;
  }
  .data-bubble-value{ font-size: 10px; }
  .data-bubble-label{ font-size: 7px; }
}


/* =========================================================
   THREAD DRIVE: STICKY TOOL SLOTS
   Uses the same .tile.tv-mark-* overlay classes as world tile marks,
   because apparently consistency survived another patch.
========================================================= */
.drive-intro,
.drive-note{
  margin: 4px 6px 10px 6px;
  padding: 8px 10px;
  font-size: 13px;
  line-height: 1.35;
  text-align: center;
  color: rgba(221,221,221,0.82);
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.45);
}

.drive-note{
  margin-top: 10px;
  opacity: 0.72;
}

.sticky-grid{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  padding: 6px;
  touch-action: pan-y !important;
}

.sticky-slot{
  min-width: 0;
  min-height: 82px;
  padding: 7px 4px 6px 4px;
  border: 2px solid #222;
  border-radius: 10px;
  background: rgba(10,10,10,0.52);
  color: #ddd;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation !important;
  box-shadow:
    0 0 2px 2px rgba(0,0,0,0.6),
    inset 0 0 0 1px rgba(255,255,255,0.04);
}

.sticky-slot.is-filled{
  border-color: rgba(255,255,255,0.18);
}

.sticky-slot.is-empty{
  opacity: 0.42;
}

.sticky-slot:active{
  background: rgba(26,26,26,0.82);
}

.sticky-tile-preview.tile{
  --tile: 48px;
  width: 48px;
  height: 48px;
  flex: 0 0 auto;
  overflow: hidden;
  border-radius: 6px;
  background-color: #111;
  background-image: none;
  image-rendering: pixelated;
}

.sticky-tile-preview .tile-layer{
  background-size: 100% 100%;
}

.sticky-slot-label{
  width: 100%;
  min-height: 12px;
  font-size: 10px;
  line-height: 1.1;
  text-align: center;
  opacity: 0.78;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 420px){
  .sticky-grid{
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .sticky-slot{
    min-height: 78px;
  }
  .sticky-tile-preview.tile{
    --tile: 42px;
    width: 42px;
    height: 42px;
  }
}


/* =========================================================
   THREAD DRIVE: STICKY CHARGES / DEPLETED TOOLS
   Finite sticky tools grey out at 0 charge, then clear on next tap.
========================================================= */
.sticky-slot{
  background:
    radial-gradient(circle at 50% 22%, rgba(255,255,255,0.06), transparent 46%),
    rgba(4,4,4,0.72);
  border-color: rgba(255,255,255,0.13);
}

.sticky-slot.is-filled{
  box-shadow:
    0 0 3px 3px rgba(0,0,0,0.75),
    inset 0 0 0 1px rgba(255,255,255,0.06),
    0 0 8px rgba(170,80,255,0.24);
}

.sticky-slot.is-depleted{
  border-color: rgba(255,40,40,0.78);
  box-shadow:
    0 0 4px 3px rgba(0,0,0,0.85),
    0 0 10px rgba(255,40,40,0.62),
    inset 0 0 0 2px rgba(255,40,40,0.35);
}

.sticky-slot-charge{
  min-height: 12px;
  font-size: 10px;
  line-height: 1;
  color: rgba(221,221,221,0.72);
  text-align: center;
}

.sticky-slot.is-depleted .sticky-slot-charge{
  color: var(--tv_aura_fail);
  font-weight: 900;
}


/* =========================================================
   THREAD DRIVE: RESPONSIVE STICKY TOOL CARDS (v34)
   Overrides the earlier square grid without changing the state model.
========================================================= */
.sticky-grid{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: 10px;
  padding: 8px 4px;
  align-items: stretch;
  touch-action: pan-y !important;
}

.sticky-slot{
  width: 100%;
  min-width: 0;
  min-height: 78px;
  padding: 9px 10px;
  border: 2px solid rgba(255,255,255,0.12);
  border-radius: 14px;
  color: #ddd;
  background:
    radial-gradient(circle at 18% 18%, rgba(255,255,255,0.07), transparent 38%),
    linear-gradient(135deg, rgba(18,18,22,0.88), rgba(2,2,4,0.94));
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) auto;
  grid-template-areas: "preview text charge";
  justify-items: stretch;
  align-items: center;
  align-content: center;
  column-gap: 10px;
  row-gap: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation !important;
  box-shadow:
    0 0 3px 3px rgba(0,0,0,0.74),
    inset 0 0 0 1px rgba(255,255,255,0.045);
}

.sticky-slot.is-filled{
  opacity: 1;
  border-color: rgba(170,80,255,0.34);
  box-shadow:
    0 0 4px 4px rgba(0,0,0,0.78),
    0 0 10px color-mix(in srgb, var(--tv_aura_void) 28%, transparent),
    inset 0 0 0 1px rgba(255,255,255,0.055);
}

.sticky-slot.is-empty{
  opacity: 0.58;
  border-color: rgba(255,255,255,0.09);
}

.sticky-slot:active{
  background:
    radial-gradient(circle at 18% 18%, rgba(255,255,255,0.09), transparent 38%),
    linear-gradient(135deg, rgba(26,26,30,0.92), rgba(4,4,8,0.96));
}

.sticky-slot.is-depleted{
  border-color: color-mix(in srgb, var(--tv_aura_fail) 80%, transparent);
  box-shadow:
    0 0 4px 4px rgba(0,0,0,0.82),
    0 0 12px color-mix(in srgb, var(--tv_aura_fail) 58%, transparent),
    inset 0 0 0 2px color-mix(in srgb, var(--tv_aura_fail) 28%, transparent);
}

.sticky-tile-preview.tile{
  grid-area: preview;
  --tile: 48px;
  width: 48px;
  height: 48px;
  min-width: 48px;
  flex: 0 0 auto;
  overflow: hidden;
  border-radius: 8px;
  background-color: #111;
  background-image: none;
  image-rendering: pixelated;
  box-shadow:
    0 0 2px 2px rgba(0,0,0,0.62),
    inset 0 0 0 1px rgba(255,255,255,0.06);
}

.sticky-tile-preview .tile-layer{
  background-size: 100% 100%;
}

.sticky-slot.is-empty .sticky-tile-preview{
  opacity: 0.34;
}

.sticky-slot-text{
  grid-area: text;
  min-width: 0;
  display: grid;
  gap: 3px;
  align-content: center;
}

.sticky-slot-label{
  width: 100%;
  min-height: 0;
  font-size: 13px;
  line-height: 1.15;
  font-weight: 900;
  text-align: left;
  opacity: 0.95;
  white-space: normal;
  overflow: visible;
  text-overflow: unset;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.sticky-slot-meta{
  font-size: 10px;
  line-height: 1.1;
  text-align: left;
  opacity: 0.62;
  text-transform: uppercase;
  letter-spacing: 0.55px;
  overflow-wrap: anywhere;
}

.sticky-slot-charge{
  grid-area: charge;
  min-width: 34px;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  justify-self: end;
  align-self: center;
  font-size: 13px;
  line-height: 1;
  font-weight: 900;
  color: rgba(221,221,221,0.82);
  background: rgba(0,0,0,0.36);
  border: 1px solid rgba(255,255,255,0.12);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.035),
    0 0 4px rgba(0,0,0,0.72);
  text-align: center;
}

.sticky-slot.is-empty .sticky-slot-charge{
  opacity: 0;
}

.sticky-slot.is-depleted .sticky-slot-charge{
  color: var(--tv_aura_fail);
  border-color: color-mix(in srgb, var(--tv_aura_fail) 45%, transparent);
  box-shadow:
    0 0 8px color-mix(in srgb, var(--tv_aura_fail) 38%, transparent),
    inset 0 0 0 1px color-mix(in srgb, var(--tv_aura_fail) 24%, transparent);
}

.sticky-slot.is-depleted .sticky-slot-meta{
  color: var(--tv_aura_fail);
  opacity: 0.9;
}

@media (max-width: 430px){
  .sticky-grid{
    grid-template-columns: 1fr;
  }
  .sticky-slot{
    min-height: 74px;
    grid-template-columns: 50px minmax(0, 1fr) auto;
    column-gap: 9px;
  }
  .sticky-tile-preview.tile{
    --tile: 44px;
    width: 44px;
    height: 44px;
    min-width: 44px;
  }
}

@media (min-width: 431px) and (max-width: 620px){
  .sticky-grid{
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}


/* =========================================================
   THREAD DRIVE: MOBILE SCROLL SAFETY PATCH (v35)
   Sticky slots are buttons, but the drive body still needs to win
   vertical drag gestures. Tiny rectangle machines demanded tribute.
========================================================= */
.drive-ui,
.drive-ui.is-open{
  touch-action: pan-y !important;
}

.drive-ui-body{
  overflow-y: auto !important;
  overflow-x: hidden !important;
  -webkit-overflow-scrolling: touch !important;
  overscroll-behavior: contain;
  touch-action: pan-y !important;
}

.drive-ui-body *,
.drive-ui .sticky-grid,
.drive-ui .sticky-slot,
.drive-ui .sticky-slot *,
.drive-ui .sticky-tile-preview,
.drive-ui .sticky-tile-preview *{
  touch-action: pan-y !important;
}

.drive-ui .sticky-slot{
  -webkit-user-select: none;
  user-select: none;
}


/* =========================================================
   iOS INPUT CONTRACT PATCH (v37)
   One contract, because mixed touch rules made Safari invent demons.
   - Game/world/control surfaces: no native gestures.
   - Scroll panel bodies: vertical scrolling only.
   - Generated tap controls inside scroll panels are protected by JS tap shield.
========================================================= */
html,
body {
  touch-action: none !important;
  overscroll-behavior: none !important;
  -webkit-text-size-adjust: 100% !important;
}

#stage,
#viewport,
#world_anchor,
#world_scale,
#world_translate,
#world,
#world *,
#thread_layer,
#thread_wrap,
#thread_sprite_stack,
#thread_sprite_stack *,
#uiShell,
#uiShell::before,
.nav-ui,
.actions-ui,
.ui-btn,
.ui_btn_generated,
.data-bubbles-shell,
.data-bubble,
.data-bubble-row {
  touch-action: none !important;
  -webkit-user-select: none !important;
  user-select: none !important;
  -webkit-touch-callout: none !important;
  -webkit-tap-highlight-color: transparent !important;
}

.panel-ui-body,
.dive-ui-body,
.drive-ui-body,
.voidBox-ui-body,
.intro-ui-body,
.auth-ui-body,
.dust-ui-body,
.data-ui-body,
.buffer-ui-body,
#dust_script_list,
#data_bubble_list,
.buffer-marks,
.buffer-string {
  touch-action: pan-y !important;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch !important;
  overscroll-behavior: contain;
}

/* Keep scrolling from card/list areas possible, but JS now owns actual taps. */
.drive-ui,
.drive-ui.is-open,
.drive-ui-body,
.drive-ui-body *,
.drive-ui .sticky-grid,
.drive-ui .sticky-slot,
.drive-ui .sticky-slot *,
#dust_script_list .ui-btn,
#dust_script_list .ui_btn_generated,
#data_bubble_list .ui-btn,
#data_bubble_list .ui_btn_generated,
.data-bubble-row,
.data-bubble-row * {
  touch-action: pan-y !important;
}

/* Non-scroll action bars stay fully gesture-proof. */
.nav-ui .ui-btn,
.actions-ui .ui-btn,
.panel-close-btn,
.panel-close-btn * {
  touch-action: none !important;
}
