/* SPDX-License-Identifier: ńL-1.0 */
/* spatial.css — Spatial Sense (normalized for ne.js + n.js)
   State model (JS-driven):
   data-sense="locked|ready|open|busy"
   data-hints="on|off"
   [data-status="1"] while preview/status text is showing
*/

/* ─── Tokens ───────────────────────────────────────────────────────── */
:root{
  --sense-blur: 2px;
  --sense-border: rgba(255,255,255,0.06);
  --sense-ring: rgba(255,255,255,0.22);
  --sense-shadow: 0 12px 38px rgba(0,0,0,0.45);
  --sense-shadow-soft: 0 6px 20px rgba(0,0,0,0.35);
  --sense-font: 500 12px/1.25 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif;
  --ui-fade-duration: .24s;
  --ui-fade-ease: ease;
}

/* ─── Group (bottom-center) ────────────────────────────────────────── */
.nSenseGroup{
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 20px);
  transform: translateX(-50%);
  width: min(100%, 400px); /* NEVER TOUCH THIS WIDTH */
  z-index: 2147483646;
  pointer-events: none;
  padding-inline: 12px;
}

/* Ensure local stacking for hint/status */
.nSenseGroup{ position: fixed; }
.nSenseGroup .nSenseBar,
.nSenseGroup .nSenseHint,
.nSenseGroup .nSenseStatus{ transition: opacity .25s ease, transform .25s ease; }

/* ─── Bar (glass) — input, hint, status share the grid lane ───────── */
.nSenseBar{
  position: relative;
  display: grid; place-items: center;
  pointer-events: auto;

  width: 100%;
  min-height: 88px;
  padding: 12px 14px;
  border-radius: 35px;

  /* explicit fallbacks first, then variable-driven */
  -webkit-backdrop-filter: saturate(1.4) blur(2px);
  backdrop-filter:         saturate(1.4) blur(2px);
  -webkit-backdrop-filter: saturate(1.4) blur(var(--sense-blur));
  backdrop-filter:         saturate(1.4) blur(var(--sense-blur));

  background-color: transparent; /* NO TINT */
  border: 1px solid var(--sense-border);
  background-clip: padding-box;

  overflow: hidden;
  isolation: isolate;

  box-shadow: 0 0 0 rgba(0,0,0,0);
  transition: box-shadow .22s ease, border-color .18s ease, transform .18s ease, opacity .22s ease;
}

/* Cursor semantics */
.nSenseBar[aria-expanded="false"]{ cursor: default; }
.nSenseBar[data-sense="open"],
.nSenseBar:focus-within{ cursor: text; border-color: var(--sense-ring); box-shadow: var(--sense-shadow-soft); outline: none; }
.nSenseBar[data-sense="busy"]{ box-shadow: var(--sense-shadow); }
.nSenseBar[data-sense="locked"]{ cursor: wait; }

/* Error pulse (JS toggles .is-error only for visual pulse) */
.nSenseBar.is-error{ animation: senseError .32s ease; }
@keyframes senseError{
  0%{ box-shadow: 0 0 0 rgba(255,255,255,0) }
  50%{ box-shadow: 0 0 0 3px rgba(255,255,255,.22) inset }
  100%{ box-shadow: 0 0 0 rgba(255,255,255,0) }
}

/* Fallback when no backdrop-filter */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .nSenseBar{
    background-color: transparent;
    border-color: rgba(255,255,255,0.12);
    box-shadow: var(--sense-shadow);
  }
}

/* ─── Input ────────────────────────────────────────────────────────── */
.nSenseInput{
  grid-area: 1 / 1;
  width: 100%; min-width: 0;
  height: 42px;
  padding: 12px 18px;

  background: transparent;
  border: none; outline: none;
  -webkit-appearance: none; appearance: none;

  color: #fff;
  text-align: center;
  font: var(--sense-font);
  letter-spacing: 0.1px;
  caret-color: rgba(255,255,255,.95);
}

/* Placeholder (kept white but faded away when interactive layers show) */
.nSenseBar .nSenseInput::placeholder,
.nSenseBar .nSenseInput::-webkit-input-placeholder{
  color: rgba(255,255,255,0.95) !important;
  opacity: 1; transition: opacity .28s ease;
}
.nSenseBar[data-sense="ready"] .nSenseInput::placeholder,
.nSenseBar[data-sense="ready"] .nSenseInput::-webkit-input-placeholder,
.nSenseBar[data-hints="on"]  .nSenseInput::placeholder,
.nSenseBar[data-hints="on"]  .nSenseInput::-webkit-input-placeholder,
.nSenseBar[data-preview="1"] .nSenseInput::placeholder,
.nSenseBar[data-preview="1"] .nSenseInput::-webkit-input-placeholder,
.nSenseBar[data-status="1"]  .nSenseInput::placeholder,
.nSenseBar[data-status="1"]  .nSenseInput::-webkit-input-placeholder,
.nSenseBar[data-sense="open"] .nSenseInput::placeholder,
.nSenseBar:focus-within      .nSenseInput::placeholder{
  opacity: 0;
}

.nSenseInput::selection{ background: rgba(255,255,255,.18); color: #fff; }

/* Closed/disabled hit-testing (no legacy .is-open) */
.nSenseInput{ pointer-events: none; }
.nSenseBar[data-sense="open"] .nSenseInput{ pointer-events: auto; }
.nSenseBar[data-sense="locked"] .nSenseInput{ cursor:not-allowed; }
.nSenseInput:disabled{ opacity:.6; cursor:not-allowed; pointer-events:none; }

/* Hide typed line while busy/processing (status layer takes over) */
.nSenseBar[data-sense="busy"] .nSenseInput{
  opacity: 0; pointer-events: none; caret-color: transparent;
}

/* ─── Hint layer (decoupled from preview/status) ───────────────────── */
.nSenseHint{
  grid-area: 1 / 1;
  z-index: 2;
  pointer-events: none; user-select: none;

  max-width: min(560px, 80vw);
  text-align: center;

  font: 500 12px/1.2 Inter,system-ui;
  color: rgba(255,255,255,.85);

  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transform: translateY(5px);
  transition: opacity .18s ease, transform .18s ease;
}

/* Subtle breathe only when visible */
@keyframes nHintBreathe{
  0%   { transform: translateY(0) }
  50%  { transform: translateY(-1px) }
  100% { transform: translateY(0) }
}

/* SHOW hint only when ready + hints:on and no status text */
.nSenseBar[data-sense="ready"][data-hints="on"]:not([data-status="1"]) .nSenseHint{
  opacity:1; transform: translateY(2px); animation: nHintBreathe 4.4s ease-in-out infinite;
}

/* Idle caret on hint */
.nSenseHint::after{
  content: "▍";
  margin-left: 6px; opacity: .9;
  animation: nCaretBlink 1s steps(1,end) infinite;
}
@keyframes nCaretBlink{ 50%{ opacity:0 } }

/* Force-hide hints when off */
.nSenseBar[data-hints="off"] .nSenseHint{
  opacity:0 !important; transform: translateY(2px) !important; animation:none !important;
}

/* ─── Status layer (preview/system messages) ───────────────────────── */
.nSenseStatus{
  grid-area: 1 / 1;
  z-index: 3;
  display: flex; align-items: center; justify-content: center; gap: 8px;

  max-width: min(560px, 80vw);
  padding: 0 6px;

  font: var(--sense-font);
  color: rgba(255,255,255,.97);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;

  opacity: 0; transform: translateY(2px);
  pointer-events: none;
  transition: opacity .16s ease, transform .16s ease;
}

/* Status is visible only while [data-status="1"] or busy */
.nSenseBar[data-status="1"] .nSenseStatus,
.nSenseBar[data-sense="busy"] .nSenseStatus{
  opacity: 1; transform: translateY(0);
}

/* But NEVER show Status while user is interacting with the field */
.nSenseBar[data-sense="open"] .nSenseStatus,
.nSenseBar:focus-within .nSenseStatus{
  opacity:0 !important; transform:translateY(2px) !important;
}

/* Optional spinner */
.nSenseSpinner{
  width: 12px; height: 12px;
  border: 2px solid rgba(255,255,255,.33);
  border-top-color: rgba(255,255,255,.9);
  border-radius: 50%;
  animation: senseSpin .8s linear infinite;
  flex: 0 0 auto;
}
@keyframes senseSpin{ to { transform: rotate(360deg) } }

/* Rotating short messages (controller toggles .active) */
.nSenseStatus .msg{
  position: absolute;
  opacity: 0; transform: translateY(4px);
  transition: opacity .14s ease, transform .14s ease;
}
.nSenseStatus .msg.active{ opacity:1; transform: translateY(0); }

/* Order-agnostic safety */
.nSenseBar .nSenseHint, .nSenseBar .nSenseStatus{ opacity:0; transform:translateY(2px); }

/* While OPEN or when status present/busy, hints must be hidden */
.nSenseBar[data-sense="open"] .nSenseHint,
.nSenseBar[data-status="1"]   .nSenseHint,
.nSenseBar[data-sense="busy"] .nSenseHint{
  opacity:0 !important; transform: translateY(2px) !important;
}

/* ─── Compatibility: class-based pipeline (.is-processing / .is-error) ─
   These ensure status wins if other modules toggle classes on .nSenseGroup.
----------------------------------------------------------------------- */
.nSenseGroup.is-processing .nSenseHint{ opacity:0 !important; pointer-events:none; }
.nSenseGroup.is-processing .nSenseStatus{ opacity:1 !important; pointer-events:auto; }
.nSenseGroup.is-error .nSenseHint{ opacity:0 !important; pointer-events:none; }
.nSenseGroup.is-error .nSenseStatus{ opacity:1 !important; pointer-events:auto; }
.nSenseGroup.is-processing .nSenseInput{ pointer-events:none; }

/* ─── Command ribbon (Press / or Cmd+K…) — optional element ───────── */
.nCommandRibbon{
  position: absolute; inset-inline: 12px; bottom: 10px;
  text-align: center; font: var(--sense-font);
  color: rgba(255,255,255,.66);
  pointer-events: none; opacity: 1; transition: opacity .16s ease;
}
.nSenseBar[data-sense="open"] .nCommandRibbon,
.nSenseBar:focus-within .nCommandRibbon,
.nSenseBar[data-status="1"] .nCommandRibbon,
.nSenseBar:has(.nSenseInput:not(:placeholder-shown)) .nCommandRibbon,
.nSenseBar[data-has-value="1"] .nCommandRibbon{
  opacity: 0;
}

/* ─── Bar reveal (keeps backdrop-filter intact) ────────────────────── */
.nSenseBar{
  opacity: 0;
  will-change: opacity, -webkit-backdrop-filter, backdrop-filter;
  transform: translateZ(0);
}
.nInterface.visible .nSenseBar{
  animation: nSenseBarFade var(--ui-fade-duration) var(--ui-fade-ease) forwards;
  animation-delay: .32s;
}
@keyframes nSenseBarFade{ from{opacity:0} to{opacity:1} }

/* Optional reveal tick */
.nSenseBar.reveal{ box-shadow: 0 0 0 1px rgba(255,255,255,.08) inset; }

/* ─── Response Dock & Tiles (animations + hit-testing) ────────────── */
#nResponseDock{
  z-index: 2147483645;
  pointer-events: none; /* re-enable on interactive children only */
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  width: min(100%, 720px);
  margin: 0 auto;
  padding: 10px 12px 0;
}

/* Tile defaults */
.nResponseTile{
  pointer-events: auto;
  max-width: 100%;
  border-radius: 18px;
  backdrop-filter: saturate(1.1) blur(1.5px);
  -webkit-backdrop-filter: saturate(1.1) blur(1.5px);
  border: 1px solid rgba(255,255,255,.06);
  background: rgba(0,0,0,.18);
  color: #fff;
  padding: 14px 16px;
  transform-origin: bottom center;
  animation: tileEnter .16s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes tileEnter{
  from{ opacity:0; transform: translateY(6px) scale(.985) }
  to  { opacity:1; transform: translateY(0)    scale(1) }
}

/* Hide/collapse */
.nResponseTile.is-exiting{
  animation: tileExit .16s cubic-bezier(.2,.8,.2,1) forwards;
}
@keyframes tileExit{
  to { opacity:0; transform: translateY(6px) scale(.985) }
}

/* Collapsible height helper (JS sets height → 0) */
.nResponseTile.collapsing{
  overflow: hidden; transition: height .16s ease, opacity .16s ease;
}

/* Make only CTA rows clickable */
.nResponseTile .action{ pointer-events: auto; }

/* ─── Rate-limit & layering ────────────────────────────────────────── */
canvas.webgl, .webgl-canvas, #webgl-canvas{ pointer-events: auto; z-index: auto; }
#nNotify{ z-index: 2147483644; }

/* ─── Reduced motion ───────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .nSenseHint, .nSenseStatus{ transition-duration: .1s; animation-duration: .1s }
  .nSenseSpinner{ animation-duration: 1.2s }
  .nResponseTile{ animation-duration: .1s }
}
