/* Jarvis web — a HUD reworked from adewaskar/jarvis (MIT, see NOTICE.txt).
   One self-hosted face (Exo 2, OFL). Colour is spent on state only: cyan = listening, amber = thinking,
   white = speaking, red = trouble. The reactor from the boot stays and becomes the HUD's centre. */
@font-face { font-family: "Exo 2"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(fonts/exo-2-latin-wght-normal.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Exo 2"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(fonts/exo-2-latin-ext-wght-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Exo 2"; font-style: normal; font-display: swap; font-weight: 100 900;
  src: url(fonts/exo-2-cyrillic-wght-normal.woff2) format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }

:root {
  --bg: #070b10;
  --panel: #0c151e;      /* one tone step up from the ground: surfaces, not outlines */
  --raise: #122030;      /* a second step: buttons */
  --line: #1c2b38;
  --line-strong: #2d4152;
  --text: #dce7ef;
  --muted: #8ea3b4;
  --accent: #5cd3ff;     /* listening / focus */
  --think: #ffb84d;      /* thinking */
  --speak: #f2f7fa;      /* speaking */
  --bad: #ff7a70;        /* errors */
  --state: var(--line-strong);
  --lvl: 0;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --t: 200ms;
  --s-1: 0.25rem; --s0: 0.5rem; --s1: 0.75rem; --s2: 1rem; --s3: 1.5rem; --s4: 2.25rem;
  --f-sm: 0.889rem; --f-md: 1rem; --f-lg: 1.266rem; --f-xl: 1.802rem;
  font-family: "Exo 2", system-ui, sans-serif;
  font-size: 100%;
  color: var(--text);
  background: var(--bg);
}
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body { min-height: 100dvh; line-height: 1.5; -webkit-font-smoothing: antialiased; }
button, input, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- layout ---------- */
.stage {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr auto auto;
  grid-template-areas: "top" "reactor" "status" "log" "controls" "credit";
  gap: var(--s1);
  padding: max(var(--s2), env(safe-area-inset-top)) var(--s2) max(var(--s1), env(safe-area-inset-bottom));
  max-width: 76rem;
  margin: 0 auto;
}
.stage[data-view="boot"], .stage[data-view="login"] {
  grid-template-rows: 1fr auto auto auto 1fr;
  grid-template-areas: "." "reactor" "status" "login" ".";
  justify-items: center;
}
.topbar { grid-area: top; }
.reactor-wrap { grid-area: reactor; display: grid; place-items: center; }
.status { grid-area: status; }
.login { grid-area: login; }
.log { grid-area: log; }
.controls { grid-area: controls; }
.credit { grid-area: credit; }
.stage > * { min-width: 0; }

@media (min-width: 60rem) {
  .stage[data-view="hud"] {
    grid-template-columns: minmax(18rem, 26rem) minmax(0, 1fr);
    grid-template-rows: auto 1fr 1fr auto auto;
    grid-template-areas: "top top" "reactor log" "status log" "controls controls" "credit credit";
    height: 100dvh;
    column-gap: var(--s4);
  }
  .stage[data-view="hud"] .reactor-wrap { align-self: end; }
  .stage[data-view="hud"] .status { align-self: start; text-align: center; }
}

/* ---------- reactor ---------- */
.reactor { width: min(72vw, 44dvh, 28rem); height: auto; overflow: visible; transition: width 600ms var(--ease); }
.stage[data-view="hud"] .reactor { width: min(44vw, 11rem); }
@media (min-width: 60rem) { .stage[data-view="hud"] .reactor { width: min(28vw, 24rem); } }
.reactor circle { fill: none; transform-origin: 100px 100px; transition: stroke var(--t) linear, opacity var(--t) linear; }
.r-ticks { stroke: #36506a; stroke-width: 3; stroke-dasharray: 1 4; }
.r-outer { stroke: var(--line-strong); stroke-width: 1; }
.r-arcs { stroke: var(--state); stroke-width: 3; stroke-dasharray: 70 50; }
.r-coils { stroke: var(--state); stroke-width: 12; stroke-dasharray: 27 9; opacity: calc(0.45 + var(--lvl) * 0.55); }
.r-inner { stroke: var(--line-strong); stroke-width: 1.5; }
.r-core { fill: var(--state); transform: scale(calc(0.75 + var(--lvl) * 0.5)); transition: transform 90ms linear, fill var(--t) linear; }

.stage[data-state="idle"]      { --state: #4d7391; }
.stage[data-state="listening"] { --state: var(--accent); }
.stage[data-state="armed"]     { --state: #2f8db3; }
.stage[data-state="thinking"]  { --state: var(--think); }
.stage[data-state="speaking"]  { --state: var(--speak); }
.stage[data-state="error"]     { --state: var(--bad); }

@media (prefers-reduced-motion: no-preference) {
  .r-ticks { animation: spin 60s linear infinite; }
  .r-arcs { animation: spin 14s linear infinite reverse; }
  .stage[data-state="thinking"] .r-arcs { animation-duration: 2.4s; }
  .stage[data-state="listening"] .r-arcs { animation-duration: 6s; }
  /* the one boot: rings draw in, then the core lights */
  .booting .reactor circle:not(.r-core) { stroke-dashoffset: 360; animation: draw 700ms var(--ease) both, spin 60s linear infinite; }
  .booting .r-arcs, .booting .r-coils { stroke-dasharray: 360; }
  .booting .r-outer { animation-delay: 80ms; }
  .booting .r-arcs { animation-delay: 160ms; }
  .booting .r-coils { animation-delay: 240ms; }
  .booting .r-inner { animation-delay: 320ms; }
  .booting .r-core { animation: core 500ms var(--ease) 450ms both; }
  /* entrance: bar, then the conversation, then the controls, 80ms apart */
  .topbar, .panel, .controls, .status { animation: rise 520ms var(--ease) both; }
  .status { animation-delay: 520ms; }
  .panel { animation-delay: 80ms; }
  .controls { animation-delay: 160ms; }
  .msg { animation: rise 360ms var(--ease) both; }
  button:active { transform: translateY(1px); }
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes core { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(0.75); } }
@keyframes rise { from { opacity: 0; transform: translateY(1.25rem); } to { opacity: 1; transform: none; } }

/* ---------- type ---------- */
.wordmark { margin: 0; font-size: 2.281rem; font-weight: 600; letter-spacing: 0.32em; text-indent: 0.32em; text-align: center; }
.wordmark.small { font-size: var(--f-md); letter-spacing: 0.28em; text-indent: 0; }
.status { margin: 0; min-height: 1.5em; font-size: var(--f-lg); font-weight: 500; color: var(--state); text-align: center; font-variant-numeric: tabular-nums; }
.stage[data-state="idle"] .status { color: var(--muted); }
.stage[data-state="error"] .status { color: var(--bad); }
.hint { margin: 0; font-size: var(--f-sm); color: var(--muted); max-width: 34rem; }
.error { margin: var(--s1) 0 0; color: var(--bad); font-size: var(--f-sm); }

/* ---------- panels with corner brackets ---------- */
.panel {
  position: relative;
  background: var(--panel);
  padding: var(--s3);
}
.panel::before, .panel::after {
  content: ""; position: absolute; width: 0.875rem; height: 0.875rem; pointer-events: none;
  border-color: var(--line-strong); border-style: solid;
}
.panel::before { top: 0; left: 0; border-width: 2px 0 0 2px; }
.panel::after { right: 0; bottom: 0; border-width: 0 2px 2px 0; }

/* ---------- login ---------- */
.login { width: min(100%, 26rem); display: grid; gap: var(--s2); }
.step { display: grid; gap: var(--s1); }
label { font-size: var(--f-sm); color: var(--muted); }
input[type="text"], input:not([type]), input[inputmode], textarea {
  width: 100%; min-height: 2.75rem; padding: var(--s0) var(--s1);
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: 2px;
  font-size: var(--f-md);
  transition: border-color var(--t) var(--ease);
}
input:focus, textarea:focus { border-color: var(--accent); outline: none; }
#code { font-size: var(--f-lg); letter-spacing: 0.5em; text-align: center; font-variant-numeric: tabular-nums; }

button { cursor: pointer; min-height: 2.75rem; padding: var(--s0) var(--s2); border-radius: 2px; border: 1px solid transparent; /* taste-skill-ignore: invisible, keeps the mic's pressed ring from shifting */ background: var(--raise); transition: border-color var(--t) var(--ease), background-color var(--t) var(--ease), color var(--t) var(--ease), transform 90ms var(--ease); }
button:hover { background: #18293b; }
button:disabled { opacity: 0.5; cursor: progress; }
button.primary { background: var(--text); color: var(--bg); border-color: var(--text); font-weight: 600; }
button.primary:hover { background: #ffffff; }
button.ghost { background: transparent; color: var(--muted); }
button.ghost:hover { color: var(--text); background: var(--raise); }
button.link { border: 0; background: transparent; padding: 0; min-height: 2rem; color: var(--muted); text-decoration: underline; justify-self: start; }

/* ---------- HUD ---------- */
.topbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s2); padding-bottom: var(--s1); }
.topbar > * { flex-shrink: 0; }
.topbar .who { flex: 1 1 auto; min-width: 0; }
.who { margin-left: auto; font-size: var(--f-sm); color: var(--muted); text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.log { display: flex; flex-direction: column; min-height: 14rem; max-height: calc(100dvh - 22rem); padding: var(--s2); overflow: hidden; }
@media (min-width: 60rem) { .log { max-height: calc(100dvh - 15rem); } }
.log-list { list-style: none; margin: 0; padding: 0 var(--s0) 0 0; overflow-y: auto; display: grid; gap: var(--s2); align-content: start; overscroll-behavior: contain; }
.empty { margin: auto; max-width: 26rem; color: var(--muted); font-size: var(--f-lg); text-align: center; text-wrap: balance; }
.msg { display: grid; gap: var(--s-1); }
.msg .who-line { font-size: var(--f-sm); font-weight: 600; color: var(--muted); }
.msg.me .body { color: var(--muted); white-space: pre-wrap; }
.msg.jarvis { background: #101b26; padding: var(--s1) var(--s2); border-left: 3px solid var(--line-strong); }
.msg.jarvis.live { border-left-color: var(--state); }
.msg.err .body { color: var(--bad); }
.body { overflow-wrap: anywhere; max-width: 70ch; }
.body p { margin: 0 0 var(--s0); }
.body p:last-child { margin-bottom: 0; }
.body ul, .body ol { margin: 0 0 var(--s0); padding-left: 1.25rem; }
.body code { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 0.9em; background: var(--bg); padding: 0 0.25em; }
.body pre { margin: 0 0 var(--s0); padding: var(--s1); background: var(--bg); overflow-x: auto; }
.body pre code { padding: 0; }
.body a { color: var(--accent); }
.body table { border-collapse: collapse; font-size: var(--f-sm); display: block; overflow-x: auto; margin-bottom: var(--s0); }
.body th, .body td { border: 1px solid var(--line); padding: var(--s-1) var(--s0); text-align: left; }
.body h3 { font-size: var(--f-md); margin: var(--s1) 0 var(--s-1); }

.controls { display: grid; gap: var(--s1); }
.composer { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s0); }
textarea { resize: none; max-height: 10rem; line-height: 1.5; }
.voicebar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); }
.mic { display: inline-flex; align-items: center; gap: var(--s0); padding-inline: var(--s2) var(--s3); }
.mic-dot { width: 0.75rem; height: 0.75rem; border-radius: 50%; border: 2px solid var(--muted); transition: background-color var(--t) linear, border-color var(--t) linear; }
.mic[aria-pressed="true"] { border-color: var(--accent); background: #0f2a38; }
.mic[aria-pressed="true"] .mic-dot { background: var(--accent); border-color: var(--accent); }
.toggle { display: inline-flex; align-items: center; gap: var(--s0); color: var(--text); font-size: var(--f-sm); min-height: 2.75rem; cursor: pointer; }
.toggle input { width: 1.125rem; height: 1.125rem; accent-color: var(--accent); }
.keys { display: none; }
@media (hover: hover) and (min-width: 60rem) { .keys { display: block; } }

.credit { text-align: center; font-size: 0.79rem; }
.credit a { color: var(--muted); }
.noscript { padding: var(--s3); text-align: center; }

@media (max-width: 40rem) {
  /* phone: the name gets its own line under the wordmark instead of an ellipsis */
  .topbar .who { order: 3; flex-basis: 100%; margin: 0; text-align: left; }
  .topbar #logout { margin-left: auto; }
}
@media (max-width: 26rem) {
  .stage { padding-inline: var(--s1); }
  .panel { padding: var(--s2); }
  .voicebar .toggle span { font-size: 0.85rem; }
}
