/* Sahaay UI.
   OLED black: this sits next to a lecture video for an hour, and a bright
   panel beside it is genuinely tiring. True #000 also switches the pixels
   off on an OLED laptop, which is battery over a long lecture. Caption type is large and
   user-resizable because the primary user may be reading rather than
   hearing the lecture. */

:root {
  color-scheme: dark;
  --bg: #000000;
  /* Panels are nearly opaque so the matrix behind reads as texture, never
     as something competing with a caption. */
  --surface: rgba(9, 10, 12, 0.86);
  --surface-2: #101215;
  --line: #1d2025;
  --line-hi: #2c3139;
  --text: #ececec;
  --text-dim: #8b919a;
  --accent: #4db8ff;
  --accent-dim: #07161f;
  --accent-glow: rgba(77, 184, 255, 0.28);
  --npu: #00d68f;
  --warn: #ffb020;
  --danger: #ff5c5c;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* Captions scale with the viewport but stay inside a readable band, and
     --cap-scale is nudged by the A+/A− controls. */
  --cap-scale: 1;
  --cap-size: calc(clamp(1.05rem, 0.9rem + 0.7vw, 1.6rem) * var(--cap-scale));

  --radius: 12px;
  --gap: clamp(0.75rem, 0.5rem + 1vw, 1.5rem);
}

* { box-sizing: border-box; }

/* The [hidden] attribute only works because the UA stylesheet sets
   display:none on it, and ANY class rule with a display property beats that
   on specificity. `.sheet { display: flex }` silently defeated it, so the
   session-notes panel sat on screen permanently, covering the captions.
   Caught by actually screenshotting the page rather than testing the DOM.
   This rule has to come before the components that set display. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.55 "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, sans-serif;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

h1, h2 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }

/* The matrix (matrix.js) sits behind everything and never takes a click. */
.matrix-bg {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}
/* It starts once the page is idle, and fades in rather than popping. */
.matrix-bg { opacity: 0; transition: opacity 0.8s ease; }
.matrix-bg.on { opacity: 1; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- header ---------- */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 0.7rem var(--gap);
  background: rgba(0, 0, 0, 0.72);
  border-bottom: 1px solid var(--line);
  animation: enter 0.5s var(--ease) both;
}

.brand { display: flex; align-items: center; gap: 0.7rem; }
.brand h1 { font-size: 1.05rem; letter-spacing: 0.01em; }
.logo { width: 34px; height: 34px; flex: none; display: block;
        transition: transform 0.35s var(--ease), filter 0.35s var(--ease); }
.brand:hover .logo { transform: rotate(-6deg) scale(1.06); filter: drop-shadow(0 0 10px var(--accent-glow)); }
.tag { margin: 0; font-size: 0.7rem; color: var(--text-dim); letter-spacing: 0.08em; text-transform: uppercase; }

.bar-right { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }

.badge {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  font-size: 0.8rem; font-weight: 500;
  background: var(--surface-2);
  border: 1px solid var(--line);
  white-space: nowrap;
  transition: color 0.3s, border-color 0.3s, background 0.3s;
}
.badge .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--text-dim);
  flex: none;
}
.badge-npu { color: var(--npu); border-color: color-mix(in srgb, var(--npu) 40%, transparent); }
.badge-npu .dot { background: var(--npu); box-shadow: 0 0 0 3px color-mix(in srgb, var(--npu) 20%, transparent);
                  animation: breathe 2.4s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: 0.45; } }
.badge-cpu { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.badge-cpu .dot { background: var(--warn); }
.badge-muted { color: var(--text-dim); }

select, .btn {
  font: inherit;
  font-size: 0.875rem;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s, color 0.2s,
              box-shadow 0.25s var(--ease), transform 0.2s var(--ease);
}
select:focus-visible, .btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn:hover:not(:disabled) { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.btn:active:not(:disabled) { transform: scale(0.97); }
select:hover { border-color: var(--line-hi); }
a.btn { text-decoration: none; display: inline-block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #04121c;
  font-weight: 600;
  min-width: 5.5rem;
}
.btn-primary:hover:not(:disabled) { box-shadow: 0 0 18px var(--accent-glow); }
.btn-primary.recording {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
  position: relative;
}
/* A ring that pulses outward while recording. Transform and opacity only,
   so the compositor does it without repainting anything. */
.btn-primary.recording::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 2px solid var(--danger);
  animation: pulse 1.8s var(--ease) infinite;
  pointer-events: none;
}
@keyframes pulse {
  from { opacity: 0.7; transform: scale(1); }
  to { opacity: 0; transform: scale(1.25, 1.6); }
}
.btn-icon { padding: 0.35rem 0.5rem; min-width: 0; }

/* ---------- layout ---------- */

main {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(240px, 26vw, 360px);
  gap: var(--gap);
  padding: var(--gap);
  min-height: 0;
}

@media (max-width: 820px) {
  main { grid-template-columns: 1fr; grid-template-rows: 1fr auto; }
  .side { max-height: 40vh; }
}

.live, .side {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  transition: border-color 0.3s;
  animation: enter 0.55s var(--ease) both;
}
.live { animation-delay: 0.06s; }
.side { animation-delay: 0.12s; }
.live:hover, .side:hover { border-color: var(--line-hi); }

@keyframes enter {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.live-head, .side-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; flex-wrap: wrap;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--line);
}
.side-head { border-bottom: none; padding-bottom: 0.3rem; }
.live-head h2, .side-head h2 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-dim); }

.live-meta { display: flex; align-items: center; gap: 0.5rem; }
.text-size { display: flex; gap: 0.25rem; }

.pill {
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  background: var(--surface-2);
  border-radius: 6px;
  padding: 0.2rem 0.5rem;
  transition: color 0.3s;
}
.pill.good { color: var(--npu); }
.pill.bad { color: var(--warn); }

/* ---------- captions ---------- */

.captions {
  list-style: none;
  margin: 0;
  padding: 1rem;
  overflow-y: auto;
  flex: 1;
  scroll-behavior: smooth;
}
/* Until the first caption the list is empty and must not claim the panel,
   or the "Press Start" hint is pushed to the bottom instead of centred. */
.captions:empty { flex: 0; padding: 0; }

.cap {
  padding: 0.7rem 0.9rem;
  border-radius: 10px;
  margin-bottom: 0.6rem;
  background: var(--surface-2);
  border-left: 3px solid transparent;
  transition: border-color 0.4s, background 0.4s;
  animation: rise 0.32s var(--ease);
}
.cap:last-child { background: #0c1117; }
.cap:last-child { border-left-color: var(--accent); }

@keyframes rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes slide-in {
  from { opacity: 0; transform: translateX(12px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .captions { scroll-behavior: auto; }
}

.cap-src {
  font-size: var(--cap-size);
  line-height: 1.45;
  margin: 0;
}
.cap-tr {
  font-size: calc(var(--cap-size) * 0.92);
  color: var(--accent);
  margin: 0.35rem 0 0;
  line-height: 1.5;
  transition: opacity 0.3s;
  animation: rise 0.3s var(--ease);
}
/* Still arriving: slightly dimmer, with a caret where the next word lands. */
.cap-tr.partial { opacity: 0.78; }
.cap-tr.partial::after {
  content: "";
  display: inline-block;
  width: 0.08em;
  height: 1em;
  margin-left: 0.15em;
  vertical-align: -0.12em;
  background: currentColor;
  animation: caret 0.9s steps(1, end) infinite;
}
@keyframes caret { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cap-tr.partial::after { animation: none; } }
.cap-foot {
  display: flex; gap: 0.6rem; flex-wrap: wrap;
  margin-top: 0.4rem;
  font-size: 0.68rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.cap-src { transition: opacity 0.25s; }
.cap-partial { opacity: 0.55; font-style: italic; }

.empty {
  margin: auto;
  padding: 2rem;
  max-width: 34ch;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.9rem;
}
kbd {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 5px; padding: 0.1rem 0.35rem; font-size: 0.85em;
}

/* ---------- glossary ---------- */

.side { padding-bottom: 0.5rem; }
.side-hint { margin: 0 1rem 0.6rem; font-size: 0.75rem; color: var(--text-dim); }

.glossary {
  list-style: none;
  margin: 0;
  padding: 0 1rem;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.gloss {
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line);
  animation: slide-in 0.35s var(--ease);
}
.gloss:last-child { border-bottom: none; }
.gloss-term {
  font-weight: 600;
  color: var(--accent);
  font-size: 0.92rem;
}
.gloss-def { margin: 0.2rem 0 0; font-size: 0.85rem; color: var(--text); line-height: 1.45; }
.gloss-meta { margin-top: 0.25rem; font-size: 0.67rem; color: var(--text-dim); }

.devinfo {
  margin: 0;
  padding: 0 1rem 1rem;
  font-size: 0.78rem;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.3rem 0.8rem;
}
.devinfo dt { color: var(--text-dim); }
.devinfo dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; word-break: break-word; }

/* ---------- notes sheet ---------- */

.sheet {
  position: fixed;
  inset: auto 0 0 0;
  max-height: 82vh;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-radius: var(--radius) var(--radius) 0 0;
  background: #07080a;
  box-shadow: 0 -20px 60px rgba(0,0,0,0.8);
  display: flex;
  flex-direction: column;
  animation: slide 0.38s var(--ease);
  z-index: 20;
}
@keyframes slide { from { transform: translateY(100%); } to { transform: none; } }

.sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1rem var(--gap); border-bottom: 1px solid var(--line);
}
.sheet-head h2 { font-size: 1rem; }
.sheet-head > div { display: flex; gap: 0.5rem; }
.notes-path { margin: 0.6rem var(--gap) 0; font-size: 0.72rem; color: var(--text-dim); word-break: break-all; }
.notes-body {
  overflow-y: auto;
  padding: 0.5rem var(--gap) var(--gap);
  font-size: 0.9rem;
  line-height: 1.6;
}
.notes-body h2 { font-size: 0.95rem; margin: 1.2rem 0 0.4rem; color: var(--accent); }
.notes-body ul { margin: 0.3rem 0; padding-left: 1.2rem; }
.notes-body li { margin: 0.15rem 0; }
.notes-body .q { margin: 0.5rem 0; }
.notes-body details { margin-top: 0.2rem; color: var(--text-dim); }
.notes-body summary { cursor: pointer; color: var(--accent); font-size: 0.85rem; }

/* ---------- toast ---------- */

.toast {
  position: fixed;
  bottom: 1.2rem; left: 50%;
  transform: translateX(-50%);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.6rem 1rem;
  font-size: 0.85rem;
  z-index: 30;
  max-width: min(90vw, 44ch);
  box-shadow: 0 10px 30px rgba(0,0,0,0.6);
  animation: toast-in 0.28s var(--ease);
}
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.toast.error { border-color: var(--danger); color: var(--danger); }

/* ---------- input level ---------- */

/* Deliberately small and quiet: it is a reassurance, not a feature. It earns
   its place because a muted output device and a silent room produce exactly
   the same empty caption list. */
.level {
  width: 68px;
  height: 8px;
  border-radius: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  overflow: hidden;
  flex: none;
}
.level-fill {
  display: block;
  width: 0%;
  height: 100%;
  background: var(--npu);
  transition: width 0.12s linear, background 0.3s;
}
.level.silent .level-fill { background: var(--warn); }
