/* The base rules of the primitives every participant page draws: the header
   controls with the theme toggle, the connection dot, the solid toast, the
   dialog shell of shared/dialog.js, the confirm and disclaimer modal of
   shared/utils.js and shared/disclaimer.js, and the pause hold.

   Readers: index.html, mm.html, cm.html, st.html, pb.html and projector.html.
   Each loads this sheet after base.css, components.css and the lockups, and
   before its sim sheet, so a sim sheet changes a primitive by restating a
   declaration under the same selector. A sim sheet keeps only its own
   placement and its own values. The trainer and admin pages load console.css,
   which keeps its own copies by the ruling of 2026-08-26.

   Each of these blocks was copied into two or three sim sheets before
   2026-11-06. A page that did not have its copy drew the About dialog or the
   Disclaimer as unstyled text at the foot of the page. */

/* ── Header, right-hand controls ───────────────────────────────────── */

/* The Bank ALM console header (css/console.css .header-controls,
   .theme-toggle and its glyph swap, .btn / .btn-secondary), so the theme
   toggle and the Leave or Sign Out button sit exactly where they sit there:
   one group, centred on the header's middle line. Console tokens are
   substituted by their values where the platform has no equivalent:
   --radius-sm is --r-sm, --font-base is --font, and --bg-hover, which the
   platform does not define, is --bg-elevated. The two participant headers keep their own ids,
   #pm-header-controls (hedge fund, Capital Markets, Prime Brokerage) and
   #mm-header-controls (market making, Sales & Trading, the projector), and
   the rules name both. With the class alone the button fell through to the
   platform's own #theme-toggle and read as a different control.

   The console header pads itself (.app-header padding: 0 24px in
   console.css); the platform header pads nothing and each right-hand child
   has its own inset instead. So the group takes the console's 24px on the
   right, which is what puts the button the same distance from the edge. */
#pm-header-controls,
#mm-header-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  padding-right: 24px;
}
#pm-header-controls .theme-toggle,
#mm-header-controls .theme-toggle {
  background: transparent;
  border: 1px solid transparent;   /* invisible by default, shows on hover */
  color: var(--text-secondary);
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  transition: var(--transition);
  /* Desaturate the colour emoji glyphs (yellow moon to grey). */
  filter: grayscale(1);
}
#pm-header-controls .theme-toggle:hover,
#mm-header-controls .theme-toggle:hover {
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text);
}
.icon-sun, .icon-moon { display: none; }
[data-theme="dark"] .icon-sun { display: inline; }
[data-theme="light"] .icon-moon { display: inline; }

#pm-header-controls .btn,
#mm-header-controls .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: var(--transition);
  border: none;
}
#pm-header-controls .btn-secondary,
#mm-header-controls .btn-secondary {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
#pm-header-controls .btn-secondary:hover,
#mm-header-controls .btn-secondary:hover {
  background: var(--bg-elevated);
  color: var(--text);
}

/* ── Connection dot ────────────────────────────────────────────────── */

/* The trainer console's dot (css/console.css .status-dot). The class names
   are the ones shared/ws.js writes, so the socket client is unchanged. The
   keyframes have a name of their own because this sheet loads beside
   base.css and components.css. The dot has no display of its own: a sim
   sheet that places it in an inline row gives it one. */
.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}
.status-dot.online { background: var(--positive); }
.status-dot.active { background: var(--color-accent); }
.status-dot.warning { background: var(--warning); }
.status-dot.offline { background: var(--negative); }
.status-dot.reconnecting {
  background: var(--warning);
  animation: status-dot-pulse 1s ease-in-out infinite;
}
@keyframes status-dot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* ── Solid toasts ──────────────────────────────────────────────────── */

/* The platform toast is a translucent tint, which was drawn to sit over a
   dark page; over a desk the message and the panel underneath read through
   each other and neither could be made out (the hedge fund desk's risk-team
   messages, and the Sales & Trading trader's deal toast, owner 2026-10-23).
   Here they take a solid card: the tint is mixed into the surface rather
   than laid over it, so nothing shows through, and the border shows which
   kind of message it is. */
.em-toast {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-weight: 500;
  line-height: 1.4;
}
/* Error toasts follow the one look ruled for every sim (owner, 2026-09-04):
   dark red border, light red fill, black text. The values are base.css's;
   they are repeated here because the `.em-toast` card above would otherwise
   win on source order and paint the error toast as a plain surface card. */
.em-toast-error {
  background: color-mix(in srgb, var(--negative) 18%, #fff);
  border-color: color-mix(in srgb, var(--negative) 60%, #000);
  color: #000;
}
.em-toast-success {
  background: color-mix(in srgb, var(--positive) 12%, var(--bg-surface));
  border-color: var(--positive);
  color: var(--text);
}
.em-toast-info {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--bg-surface));
  border-color: var(--color-accent);
  color: var(--text);
}
/* Light mode needs saying again. base.css has its own light overrides for
   these three, written as `[data-theme="light"] .em-toast-error`, and two
   selectors beat the one above however the files are ordered. So the
   translucent tint came back in light mode only, and a risk message sat over
   the instrument panel with the panel reading through the text. Same
   selector shape here, and this file loads after base.css. */
[data-theme="light"] .em-toast-error {
  background: color-mix(in srgb, var(--negative) 18%, #fff);
  color: #000;
}
[data-theme="light"] .em-toast-success {
  background: color-mix(in srgb, var(--positive) 12%, var(--bg-surface));
  color: var(--text);
}
[data-theme="light"] .em-toast-info {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--bg-surface));
  color: var(--text);
}

/* ── Dialog shell ──────────────────────────────────────────────────────
   openDialog() in shared/dialog.js builds .iro-dialog-overlay markup. These
   rules are copied from the platform's platform.css, which no participant
   page loads. The close button colour is the only change: the platform's
   is fixed white for a dark shell, and the sims run light and dark. */
.iro-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-max);
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(var(--blur-sm));
}
.iro-dialog {
  background: var(--bg-surface, #151518);
  border: 1px solid var(--border, #333);
  border-radius: 12px;
  /* The platform sizes this for charts and tables at 960px. A participant
     dialog shows a paragraph, so it takes the width the trainer and admin
     shells give the same disclaimer, which is 460px in console.css. A
     dialog that needs the room can still pass wide. */
  width: min(460px, 92vw);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
}
.iro-dialog.iro-dialog-wide { width: min(1100px, 94vw); }
.iro-dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border, #333);
  flex-shrink: 0;
}
.iro-dialog-header h3 { margin: 0; font-size: 1.1rem; font-weight: 700; }
.iro-dialog-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1.4rem;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: color 0.2s, background 0.2s;
}
.iro-dialog-close:hover { color: var(--text); background: var(--bg-elevated); }
.iro-dialog-body { flex: 1; overflow-y: auto; padding: 20px 24px; }

/* ── Confirm modal shell ─────────────────────────────────────────────
   showConfirm() in shared/utils.js and showDisclaimerModal() in
   shared/disclaimer.js build .modal-overlay / .modal-dialog markup. Copied
   from console.css "Confirm Modal", with its --radius-lg swapped for the
   platform's --r-lg (both 12px) and its --fs-body written as the 16px it is
   set to there. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  animation: modalFadeIn 150ms ease;
}
@keyframes modalFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modalSlideIn {
  from { opacity: 0; transform: translateY(-12px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Square and flat, the desk's own treatment (owner, 2026-09-10). The
   SCRIM IS UNTOUCHED: the overlay above keeps its ground and its blur,
   which is what tells a reader the desk behind is on hold. */
.modal-dialog {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 28px 32px 24px;
  min-width: 380px;
  max-width: 460px;
  box-shadow: none;
  animation: modalSlideIn 200ms ease;
}
.modal-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  padding-bottom: 12px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.modal-message {
  font-size: 16px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin-bottom: 24px;
}
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
/* Square, like the dialog around them (owner, 2026-09-10). These sit on
   the document body rather than inside a workspace, so a desk's own
   square-corner rules never reach them. */
.modal-actions .btn { border-radius: 0; }

/* ── Pause overlay ─────────────────────────────────────────────────────────
   The full-screen hold shown to every desk while the trainer has the session
   paused. Ported from the ALM sim (css/alm.css) so the sims give the same
   participant a single pause experience. mm-sim.css restates the market
   making hold's own values (no fade, a quieter icon and title) under the
   same selectors. */
/* A hold host that stays in the DOM is hidden by the attribute, and
   .pause-overlay sets display, which beats the UA [hidden] rule. */
.pause-overlay[hidden] { display: none; }
.pause-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(11, 11, 12, 0.85);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pauseFadeIn 0.3s ease;
}
[data-theme="light"] .pause-overlay {
  background: rgba(245, 245, 247, 0.85);
}
@keyframes pauseFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.pause-overlay-content {
  text-align: center;
  max-width: 520px;
  padding: 48px 40px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.pause-overlay-icon {
  font-size: 48px;
  margin-bottom: 16px;
  opacity: 0.7;
}
.pause-overlay-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--warning);
  margin-bottom: 16px;
}
.pause-overlay-hint {
  font-size: 13px;
  color: var(--text-muted);
  animation: pausePulse 2s ease-in-out infinite;
}
@keyframes pausePulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
