/* The Sentinel Orb — cyanotype HUD. One continuous shape: the orb swells to
   listen, unfolds into its panel to answer, exhales back to a ring. */

:root {
  --bg: #0A1220;
  --panel: rgba(13, 22, 38, 0.88);
  --inset: rgba(10, 18, 32, 0.6);
  --ink: #DCE8F5;
  --dim: #8FA5BF;
  --faint: #5C7191;
  --line: #24354D;
  --soft: #1A2A40;
  --cyan: #4FD8EB;
  --cyan-dim: #2A8FA6;
  --wash: rgba(79, 216, 235, 0.08);
  --amber: #E8B15C;
  --bad: #E86A6A;
  --ok: #6ADFA0;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: transparent;
  font: 14px/1.55 "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
  color: var(--ink);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  user-select: none;
}
/* Plain-browser fallback: paint a backdrop so the orb isn't floating on white. */
body.browser { background: radial-gradient(1200px 800px at 70% 20%, #0E1930 0%, var(--bg) 60%); }

.stage { position: relative; width: 100%; height: 100%; }

/* Anonymous until authenticated: only the orb, nothing else. */
body.locked .panel { display: none !important; }

/* ---------- the orb ---------- */
.orb {
  position: absolute;
  right: 18px;
  bottom: 18px;
  width: 84px;
  height: 84px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  outline: none;
  transition: transform 240ms cubic-bezier(.4, 0, .2, 1), opacity 240ms ease;
}
.orb:focus-visible .ring-main { stroke: var(--ink); }
.orb-svg { width: 100%; height: 100%; display: block; }

.ring-outer { fill: none; stroke: var(--line); stroke-width: 1; opacity: .8; }
.ring-main  { fill: rgba(10, 18, 32, 0.55); stroke: var(--cyan); stroke-width: 1.6; transform-origin: 48px 48px; }
.ring-dash  { fill: none; stroke: var(--cyan-dim); stroke-width: 1; stroke-dasharray: 4 6; opacity: .55; transform-origin: 48px 48px; }
.core       { fill: var(--cyan); transform-origin: 48px 48px; }
.wave       { stroke: var(--cyan); stroke-width: 2.4; stroke-linecap: round; opacity: 0; transform-origin: 48px 48px; }
.wave line  { transform-origin: center; }

/* idle: barely breathing */
body[data-state="idle"] .ring-main { animation: breathe 5s ease-in-out infinite; opacity: .75; }
@keyframes breathe {
  0%, 100% { transform: scale(.96); opacity: .55; }
  50%      { transform: scale(1);   opacity: .9; }
}

/* listening: the wave lives */
body[data-state="listening"] .wave { opacity: 1; }
body[data-state="listening"] .core { opacity: 0; }
body[data-state="listening"] .ring-main { stroke-width: 2; }
body[data-state="listening"] .wave line { animation: talk 700ms ease-in-out infinite alternate; }
body[data-state="listening"] .wave line:nth-child(2) { animation-delay: 90ms; }
body[data-state="listening"] .wave line:nth-child(3) { animation-delay: 180ms; }
body[data-state="listening"] .wave line:nth-child(4) { animation-delay: 270ms; }
body[data-state="listening"] .wave line:nth-child(5) { animation-delay: 360ms; }

/* working: the dashed ring turns */
body[data-state="working"] .ring-dash { animation: turn 2.4s linear infinite; opacity: .9; }
body[data-state="working"] .core { animation: corePulse 1.1s ease-in-out infinite; }

/* speaking: his voice, visible */
body[data-state="speaking"] .wave { opacity: 1; }
body[data-state="speaking"] .core { opacity: 0; }
body[data-state="speaking"] .wave line { animation: talk 520ms ease-in-out infinite alternate; }
body[data-state="speaking"] .wave line:nth-child(2) { animation-delay: 70ms; }
body[data-state="speaking"] .wave line:nth-child(3) { animation-delay: 140ms; }
body[data-state="speaking"] .wave line:nth-child(4) { animation-delay: 210ms; }
body[data-state="speaking"] .wave line:nth-child(5) { animation-delay: 280ms; }
body[data-state="speaking"] .ring-main { animation: breathe 1.6s ease-in-out infinite; }

@keyframes talk { from { transform: scaleY(.35); } to { transform: scaleY(1.15); } }
@keyframes turn { to { transform: rotate(360deg); } }
@keyframes corePulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.5); } }

@media (prefers-reduced-motion: reduce) {
  .ring-main, .ring-dash, .core, .wave line { animation: none !important; }
}

/* ---------- the panel (unfolds from the orb) ---------- */
.panel {
  position: absolute;
  right: 18px;
  bottom: 112px;
  left: 18px;
  top: 14px;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--soft);
  border-radius: 14px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, .45), 0 0 0 1px rgba(79, 216, 235, .06);
  backdrop-filter: blur(14px);
  opacity: 0;
  transform: translateY(14px) scale(.98);
  transform-origin: bottom right;
  pointer-events: none;
  transition: opacity 220ms ease, transform 260ms cubic-bezier(.4, 0, .2, 1);
}
body.open .panel { opacity: 1; transform: none; pointer-events: auto; }

.grip {
  height: 18px;
  flex: none;
  cursor: grab;
  display: flex;
  align-items: center;
  justify-content: center;
}
.grip::after {
  content: "";
  width: 44px;
  height: 3px;
  border-radius: 2px;
  background: var(--line);
}

.scroll { flex: 1; overflow-y: auto; padding: 4px 16px 8px; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }

.feed { display: flex; flex-direction: column; gap: 10px; }
.msg { max-width: 92%; }
.msg.you {
  align-self: flex-end;
  background: var(--wash);
  border: 1px solid rgba(79, 216, 235, .25);
  border-radius: 12px 12px 3px 12px;
  padding: 7px 11px;
  color: var(--ink);
}
.msg.jarvis { align-self: flex-start; color: var(--ink); padding: 2px 2px 0; }
.msg.jarvis .who {
  font: 500 9.5px/1 "IBM Plex Mono", monospace;
  letter-spacing: .2em;
  color: var(--cyan);
  display: block;
  margin-bottom: 4px;
}
.msg .note { color: var(--faint); font-style: italic; }
.msg.filler { color: var(--dim); font-style: italic; opacity: .85; padding: 2px 2px 0; }
.msg.proactive { border-left: 2px solid var(--amber); background: var(--amber-wash, rgba(232,177,92,.07)); border-radius: 3px 12px 12px 3px; padding: 7px 11px; }
.msg.proactive .who { color: var(--amber); }
.msg.proactive.urgent { border-left-color: var(--bad); }
.msg.proactive.urgent .who { color: var(--bad); }

/* Amber pulse on the orb when Jarvis surfaces something unbidden. */
body.flash .ring-main { animation: flash 0.5s ease-in-out 3 !important; }
@keyframes flash {
  0%, 100% { stroke: var(--cyan); }
  50% { stroke: var(--amber); stroke-width: 2.6; }
}
@media (prefers-reduced-motion: reduce) { body.flash .ring-main { animation: none !important; } }

.cards { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.card {
  background: var(--inset);
  border: 1px solid var(--soft);
  border-left: 2px solid var(--cyan-dim);
  border-radius: 10px;
  padding: 10px 14px;
  animation: bloom 260ms cubic-bezier(.4, 0, .2, 1);
}
@keyframes bloom { from { opacity: 0; transform: translateY(8px); } }
.card h4 { margin: 0 0 6px; font: 500 10px/1 "IBM Plex Mono", monospace; letter-spacing: .18em; text-transform: uppercase; color: var(--dim); }
.card .big { font-size: 22px; font-weight: 600; }
.card .big small { font-size: 12px; color: var(--dim); font-weight: 400; margin-left: 4px; }
.card table { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.card th { text-align: left; color: var(--faint); font-weight: 500; padding: 2px 10px 4px 0; border-bottom: 1px solid var(--soft); }
.card td { padding: 4px 10px 4px 0; border-bottom: 1px solid rgba(26, 42, 64, .5); }
.card .row { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; }
.card .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; align-self: center; }
.dot.ok { background: var(--ok); } .dot.warn { background: var(--amber); } .dot.bad { background: var(--bad); } .dot.info { background: var(--cyan); }
.card .detail { color: var(--faint); font-size: 12px; margin-left: auto; }
.card svg.chart { width: 100%; height: 64px; display: block; }

.composer { display: flex; gap: 8px; padding: 8px 14px 4px; flex: none; }
#input {
  flex: 1;
  background: var(--inset);
  border: 1px solid var(--soft);
  border-radius: 10px;
  color: var(--ink);
  font: inherit;
  padding: 9px 12px;
  outline: none;
  user-select: text;
}
#input:focus { border-color: var(--cyan-dim); box-shadow: 0 0 0 2px rgba(79, 216, 235, .12); }
#input::placeholder { color: var(--faint); font-style: italic; }
.mic {
  flex: none;
  width: 38px;
  border: 1px solid var(--soft);
  border-radius: 10px;
  background: var(--inset);
  color: var(--dim);
  cursor: pointer;
}
.mic.recording { color: #0A1220; background: var(--cyan); border-color: var(--cyan); }
.mic.hidden { display: none; }

.statusline {
  flex: none;
  display: flex;
  justify-content: space-between;
  padding: 4px 16px 10px;
  font: 400 10px/1 "IBM Plex Mono", monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
}
