/* 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: 0px;
  --sense-border: transparent;
  --sense-ring: transparent;
  --sense-shadow: none;
  --sense-shadow-soft: none;
  --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;
  --sense-bottom-offset: 1vh;
}

/* ─── Group (bottom-center) ────────────────────────────────────────── */
.nSenseGroup{
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--sense-bottom-offset, 1vh));
  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(0px);
  backdrop-filter:         saturate(1.4) blur(0px);
  -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, transparent);
  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; outline: none; }
.nSenseBar[data-sense="busy"]{ box-shadow: none; }
.nSenseBar[data-sense="locked"]{ cursor: wait; }

/* Soft ring/border when active */
.nSenseBar[data-sense="open"],
.nSenseBar:focus-within{
  --sense-border: rgba(255,255,255,.24);
  box-shadow: 0 0 0 2px rgba(255,255,255,.12);
}

/* 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: transparent;
    box-shadow: none;
  }
}

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

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

  color: #fff;
  text-align: left !important;
  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; }

/* Send button */
.nSenseSend{
  position:absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  width:44px; height:44px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.04);
  color: #fff;
  display:flex; align-items:center; justify-content:center;
  pointer-events:none;
  opacity:0;
  transform: translateY(-50%) scale(0.92);
  transition: opacity .18s ease, background-color .18s ease, transform .18s ease;
}
.nSenseSend__icon{
  width: 24px;
  height: 24px;
  display: block;
  background: currentColor;
  -webkit-mask: url("/images/icons/send.svg") center/contain no-repeat;
  mask: url("/images/icons/send.svg") center/contain no-repeat;
}
.nSenseBar[data-sense="open"] .nSenseSend,
.nSenseBar:focus-within .nSenseSend,
.nSenseSend.has-text{
  opacity:1;
  pointer-events:auto;
  transform: translateY(-50%) scale(1);
}
.nSenseSend.soft-hide{
  opacity:0;
  pointer-events:none;
  transform: translateY(-50%) scale(0.9);
}
.nSenseSend:active{ background: rgba(255,255,255,0.12); }
.nSenseSend:focus-visible{ outline:2px solid rgba(255,255,255,0.5); outline-offset:2px; }

/* 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;
}
.nSenseInput.obscured{
  color: transparent !important;
  text-shadow: 0 0 0 rgba(255,255,255,0);
  caret-color: transparent !important;
}

/* ─── 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 14px/1.2 Inter, system-ui;
  color: rgba(255,255,255,.85);

  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transform: translateY(0);
  transition: opacity .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(0); animation: none;
}

/* Idle caret on hint */
.nSenseHint::after{
  content: "▍";
  margin-left: 5px; opacity: .9;
  animation: none;
}

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

/* Font switch helper (fades while swapping) */
.nSenseHint.font-switching{
  opacity:0 !important;
}

/* Optional Pragmatica font (toggled via data-font-mode) */
@font-face{
  font-family:"Pragmatica";
  src: url("/fonts/Pragmatica-next_vf.ttf") format("truetype-variations"),
       url("/fonts/Pragmatica-next_vf.ttf") format("truetype");
  font-weight:100 900;
  font-style:normal;
  font-display:swap;
}
[data-font-mode="pragmatica"] .nSenseHint{
  font-family:"Pragmatica","Inter",system-ui;
}

/* ─── 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(0);
  pointer-events: none;
  transition: opacity .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: none; }

/* ─── 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(0px);
  -webkit-backdrop-filter: saturate(1.1) blur(0px);
  border: 0px 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 }
}
