/*
 * The specialist console, as designed.
 *
 * Ported from design/Innovad Specialist Desktop.html — a Claude Design canvas
 * export. The palette is that file's own, copied rather than reinterpreted, so
 * the page is the design rather than a version of it. It lives in tokens.css,
 * which the call screen on index.html links too.
 *
 * ## Two things about this file that will look wrong and are not
 *
 * **The shell fills the window, and the design is drawn at 1440×900.** It was
 * built to the artboard first — fixed size, centred — which put the design's
 * proportions on screen and the left edge of the sidebar off it, because a
 * flex item wider than its container overflows both sides and only one of them
 * can be scrolled to. The design is a picture of a screen, not a description
 * of one.
 *
 * **`Aeonik` is named and never loads.** It is the design's stated typeface and
 * a commercial one, and no font file ships in the canvas export — so the mockup
 * itself renders in the Helvetica Neue / Arial fallback beside it. Keeping the
 * stack verbatim means this page matches what the design actually looks like,
 * and means dropping licensed files in later changes nothing else. Do not
 * "fix" this by substituting a lookalike.
 *
 * ## What is not from the design
 *
 * Everything under "States the design does not cover". Those are real
 * conditions this product has — hot glasses, a phone that dropped, an operator
 * already in a call — that a static mockup had no reason to draw. They are
 * built from the same tokens and components so they belong, and each one says
 * what it is for.
 */


* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--color-bg);
  font-family: var(--font-body);
  color: var(--color-text);
  min-height: 100vh;
}

#app {
  /* Fills the window. The design is drawn at 1440x900 because that is a
     screen, not because the product is a picture of a screen. */
  width: 100%;
  height: 100vh;
  /* Under this the design's fixed columns - a 248px sidebar and, on the
     calendar, a 380px detail panel - leave the week grid too narrow to read.
     A sideways scrollbar is a worse day than a wide window and a better one
     than seven unreadable columns, and unlike a centred overflow it can
     actually be scrolled to. */
  min-width: 1120px;
  overflow: hidden;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  position: relative;
  display: flex;
}


/* --- states the design does not cover ------------------------------------
 *
 * A mockup draws the happy path. These are the conditions this product
 * actually produces, styled from the tokens above so they read as part of the
 * same system. Each is listed in the commit message so nothing here is a
 * silent invention.
 */

/* Waiting on something that is expected to arrive: a WHEP path that is not
   published yet, a phone reconnecting after the hourly token expiry. Not an
   error, and deliberately not styled as one. */
.state-note {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: var(--color-neutral-100);
  color: var(--color-neutral-800);
  font-size: 14px;
}

.state-note.warn { background: var(--color-warning-100); color: var(--color-warning-700); }
.state-note.danger { background: var(--color-danger-100); color: var(--color-danger-700); }

.spinner {
  width: 15px;
  height: 15px;
  flex: none;
  border: 2px solid var(--color-neutral-300);
  border-top-color: var(--color-accent);
  border-radius: 999px;
  animation: spin 0.7s linear infinite;
}

.spinner.large { width: 26px; height: 26px; border-width: 3px; }

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2.4s; }
}

/* An operator row that cannot be called, whatever the reason. The cause is
   always named in words beside it — "they're hot" sends somebody to fix the
   wrong thing when the real problem is Wi-Fi. */
.op-blocked { opacity: .55; }

/* The on-call toggle, which the design has no equivalent for: stage 4 gave the
   operator a one-tap call and somebody has to be holding the pager. */
.oncall-toggle.active {
  background: var(--color-accent-2-100);
  border-color: var(--color-accent-2-600);
  color: var(--color-accent-2-800);
}

.oncall-toggle.warn {
  background: var(--color-warning-100);
  border-color: var(--color-warning-400);
  color: var(--color-warning-700);
}

/* Which build is serving this page. Selectable, because its whole job is to be
   read out or pasted into a message. Fixed to the window rather than to #app:
   it is about the page, not about anything drawn on it. */
.version-badge {
  position: fixed;
  left: 10px;
  bottom: 10px;
  z-index: 50;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--color-neutral-300);
  background: var(--color-surface);
  color: var(--color-neutral-600);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .01em;
  user-select: all;
  white-space: nowrap;
  opacity: .8;
}

/* The signed-in wrapper is #app's only flex child on a screen page. Without
   this it is sized by its content rather than by the window - invisible while
   #app was a fixed 1440px, and not once the app fills whatever width it is
   given. min-width:0 lets the main column actually shrink rather than being
   held open by its widest row. */
#app > [data-if="signedIn"] {
  flex: 1;
  min-width: 0;
  display: flex;
}

/* The wrapper every screen's content sits in. Each screen's own scroller is
   `flex:1;overflow:auto`, which only scrolls inside a flex parent of fixed
   height. As a plain block #screen grew to its content instead, #app clipped
   the rest, and a long Pictures or Glasses page could not be scrolled at all. */
#screen {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
