* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; background: #1a1a2e; color: #e0e0e0; height: 100vh; display: flex; flex-direction: column; }

/* Recording-upload status surface (ADR-009). Fixed-positioned so it does
   not participate in body's flex column layout (which would shrink #call),
   and stays visible above fullscreen-video layouts. Child interactive
   elements re-enable pointer events on themselves. */
#persistent-status-root { position: fixed; top: 0; right: 0; z-index: 950; pointer-events: none; }
#persistent-status-root button,
#persistent-status-root a,
#persistent-status-root [role="button"] { pointer-events: auto; }

#setup {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1; gap: 16px; padding: 20px;
}
#setup h1 { font-size: 32px; color: #fff; margin-bottom: 8px; }
#setup input, #setup button {
  font-size: 20px; padding: 12px 18px; border-radius: 8px; border: none; width: 320px;
}
#setup input { background: #16213e; color: #e0e0e0; border: 1px solid #334; }
#setup input::placeholder { color: #667; }
.btn-group { display: flex; gap: 8px; }
.btn-primary { background: #0f3460; color: #fff; cursor: pointer; width: auto; }
.btn-primary:hover { background: #1a4a80; }
.btn-primary:disabled { opacity: 0.4; cursor: default; }
.btn-danger { background: #c0392b; color: #fff; cursor: pointer; width: auto; }
.btn-danger:hover { background: #e74c3c; }
.btn-mute { background: #2c3e50; color: #fff; cursor: pointer; width: auto; }
.btn-mute:hover { background: #34495e; }
.btn-mute.muted { background: #e67e22; }
.btn-mute.muted:hover { background: #f39c12; }
.btn-share { background: #2980b9; color: #fff; cursor: pointer; width: auto; }
.btn-share:hover { background: #3498db; }
.btn-share.sharing { background: #27ae60; }
.btn-share.sharing:hover { background: #2ecc71; }

#call {
  display: none; flex: 1; flex-direction: column;
}
#call-status {
  position: absolute;
  top: calc(12px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 850;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 16px;
  padding: 4px 16px;
  font-size: 13px;
  color: #ddd;
  white-space: nowrap;
}
#call-status:empty { display: none; }
#videos {
  flex: 1; position: relative; overflow: hidden; background: #000; min-height: 0;
}
#remote-video {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  object-fit: cover; background: #000;
}
#remote-video.screen-share { object-fit: contain; }
#local-video {
  position: absolute;
  bottom: calc(88px + env(safe-area-inset-bottom, 0px));
  right: calc(16px + env(safe-area-inset-right, 0px));
  width: clamp(120px, 20vw, 240px);
  aspect-ratio: 4/3;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.6);
  border: 2px solid rgba(255,255,255,0.15);
  z-index: 800;
  cursor: grab;
  touch-action: none;
  object-fit: cover;
  background: #111;
  transform: scaleX(-1); /* fallback if pip-drag.js fails; pip-drag.js owns this property at runtime */
  transition: bottom 0.3s ease;
}
#local-video:focus-visible { outline: 2px solid #4A90D9; outline-offset: 2px; }
#local-video.dragging {
  cursor: grabbing;
  /* Disable the bottom transition during drag so pip-drag.js's
   * absolute positioning updates are not fighting an in-flight
   * bottom animation (the pip-drag-transition race). */
  transition: none;
}
#local-video.pre-call {
  position: relative; bottom: auto; right: auto;
  width: 100%; height: 100%; max-width: 640px; max-height: 480px;
  margin: auto; border-radius: 8px; z-index: auto;
}
#call-controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 850;
  background: linear-gradient(transparent, rgba(0,0,0,0.6));
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
}
@media (max-width: 380px) {
  #call-controls { gap: 8px; padding: 12px 8px calc(12px + env(safe-area-inset-bottom, 0px)); }
  .ctrl-btn { width: 46px; height: 46px; }
  .ctrl-btn-end { width: 56px; height: 46px; border-radius: 23px; }
  .ctrl-btn-settings { width: 46px; height: 46px; }
}

/* --- Overlay control buttons (in-call) --- */
.ctrl-btn {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.15);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #fff;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: background-color 0.15s ease;
}
.ctrl-btn:active { background: rgba(255,255,255,0.3); transform: scale(0.95); }
.ctrl-btn:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 0;
  box-shadow: 0 0 0 4px rgba(0,0,0,0.6);
}
.ctrl-btn-end:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 0;
  box-shadow: 0 0 0 4px rgba(0,0,0,0.6);
}
.ctrl-btn svg { width: 24px; height: 24px; }
.ctrl-btn.muted { background: rgba(255,255,255,0.35); }
.ctrl-btn.sharing { background: rgba(52,199,89,0.5); }
.ctrl-btn.recording { background: rgba(192,57,43,0.8); }
.ctrl-btn-end { width: 64px; height: 52px; border-radius: 26px; background: #FF3B30; }
.ctrl-btn-end:active { background: #CC2F27; }

#status {
  font-size: 14px; color: #aaa; padding: 6px 12px; text-align: center;
  background: #16213e;
}

/* Call entry point states (call.html) */
#call-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; flex: 1; color: #aaa; font-size: 18px; }
#call-error { display: none; flex-direction: column; align-items: center; justify-content: center; flex: 1; color: #e74c3c; font-size: 18px; }
#call-ended { display: none; flex-direction: column; align-items: center; justify-content: center; flex: 1; color: #aaa; font-size: 18px; }

/* Recording */
.btn-record { background: #2c3e50; color: #fff; cursor: pointer; width: auto; }
.btn-record:hover { background: #34495e; }
.btn-record.recording { background: #c0392b; }
.btn-record:disabled { opacity: 0.4; cursor: default; }

.recording-indicator {
  display: none;
  position: absolute;
  top: calc(12px + env(safe-area-inset-top, 0px));
  right: calc(12px + env(safe-area-inset-right, 0px));
  z-index: 850;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 16px;
  padding: 6px 14px;
  color: #e74c3c;
  font-weight: bold;
  font-size: 14px;
}
.recording-dot {
  width: 10px; height: 10px; border-radius: 50%; background: #e74c3c;
  animation: pulse-dot 1.2s ease-in-out infinite;
}
@keyframes pulse-dot {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}
.btn-small {
  font-size: 13px; padding: 4px 12px; border-radius: 6px; border: none;
  background: #2c3e50; color: #fff; cursor: pointer;
}
.btn-small:hover { background: #34495e; }
.btn-small.btn-danger { background: #c0392b; }
.btn-small.btn-danger:hover { background: #e74c3c; }

/* Consent modal */
.modal-overlay {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  background: rgba(0,0,0,0.7); display: none; align-items: center;
  justify-content: center; z-index: 1000;
}
.modal-content {
  background: #16213e; padding: 32px; border-radius: 12px; text-align: center;
  max-width: 400px; width: 90%;
}
.modal-content h2 { margin-bottom: 12px; color: #fff; }
.modal-content p { margin-bottom: 20px; color: #ccc; }
.modal-content .btn-group { justify-content: center; }

/* Recordings panel */
.btn-secondary {
  background: #2c3e50; color: #aaa; cursor: pointer; border: none;
  font-size: 16px; padding: 10px 20px; border-radius: 8px; margin-top: 8px;
}
.btn-secondary:hover { background: #34495e; color: #fff; }
.recordings-panel {
  position: fixed; top: 0; right: 0; width: 380px; height: 100%;
  background: #16213e; border-left: 1px solid #334; z-index: 900;
  display: none; flex-direction: column; overflow-y: auto;
}
.recordings-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 16px 20px; border-bottom: 1px solid #334;
}
.recordings-header h2 { color: #fff; font-size: 18px; }
.recordings-empty { color: #667; text-align: center; padding: 40px 20px; }
.recording-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 20px; border-bottom: 1px solid #222;
}
.recording-row:hover { background: #1a2744; }
.recording-partial { opacity: 0.7; }
.recording-info { display: flex; flex-direction: column; gap: 2px; }
.recording-date { color: #e0e0e0; font-size: 14px; }
.recording-meta { color: #888; font-size: 12px; }
.recording-actions { display: flex; gap: 6px; }

/* Safety number
 * The bar is always visible when a safety number has been derived
 * (JS toggles display:flex via the existing lifecycle path). It is
 * tappable to open the Verify modal. The auto-hide group does NOT
 * include this element — it is a persistent trust signal.
 */
.safety-number-bar {
  display: none;
  position: absolute;
  bottom: calc(88px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 840;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 16px;
  padding: 4px 10px;
  color: #4ade80;
  font-size: 11px;
  font-family: monospace;
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
.safety-number-bar:hover {
  background: rgba(0,0,0,0.6);
  transform: translateX(-50%) translateY(-1px);
}
.safety-number-bar:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
}
/* Applied by signaling.js when safety_number_verified_ack is received.
 * We tint AFTER the server ack so the UI never claims verification the
 * audit log cannot back up (Compliance gate 2 M1). */
.safety-number-bar.verified {
  background: #0a2810;
}
.safety-number-bar.verified:hover {
  background: #0d351a;
}
.safety-lock { font-size: 14px; }
.safety-number-display {
  font-family: monospace; font-size: 28px; letter-spacing: 4px;
  color: #4ade80; padding: 20px; background: #0a1628; border-radius: 8px;
  margin-bottom: 16px; line-height: 1.6;
}
.safety-hint { font-size: 12px; color: #888; margin-bottom: 16px; }
#safety-number-bar .btn-small { display: none; }

/* --- Connection badge --- */
.connection-badge {
  display: none;
  position: absolute;
  top: calc(12px + env(safe-area-inset-top, 0px));
  left: calc(12px + env(safe-area-inset-left, 0px));
  z-index: 900;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 12px;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 12px;
  font-weight: 500;
  color: #fff;
  cursor: pointer;
  user-select: none;
  transition: background-color 0.15s ease, opacity 0.2s ease;
}
.connection-badge:hover {
  background: rgba(0,0,0,0.65);
}
.connection-badge:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
}
/* Transitional state: ICE disconnected/checking/failed or last-resort
 * candidate-pair. The label text is replaced with "Reconnecting..." by
 * JS via the updateBadgeTransitional() helper. The opacity serves as
 * a visual marker so the user sees the state is uncertain without the
 * badge disappearing entirely (which would lose all transport context). */
.connection-badge.transitioning {
  opacity: 0.6;
}
.connection-badge-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.connection-badge.p2p .connection-badge-dot { background: #34C759; }
.connection-badge.relay .connection-badge-dot { background: #FF9500; }

/* Transport tooltip — hardcoded-string speech bubble shown above the
 * connection badge when the user taps or keyboard-activates it. Text
 * content is set via .textContent in connection-monitor.js (no
 * innerHTML, no interpolation of getStats or SDP fields). Auto-dismiss
 * after 4 seconds or on the next click/keydown. */
.transport-tooltip {
  display: none;
  position: absolute;
  top: calc(42px + env(safe-area-inset-top, 0px));
  left: calc(12px + env(safe-area-inset-left, 0px));
  z-index: 905;
  max-width: 260px;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgba(20, 20, 40, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: #e0e0e0;
  font-size: 12px;
  line-height: 1.4;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  border: 1px solid rgba(255,255,255,0.12);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
.transport-tooltip.visible {
  display: block;
  opacity: 1;
}

/* --- Responsive: short viewports (landscape phones) --- */
@media (max-height: 500px) {
  .ctrl-btn { width: 44px; height: 44px; }
  .ctrl-btn svg { width: 20px; height: 20px; }
  .ctrl-btn-end { width: 56px; height: 44px; border-radius: 22px; }
  #call-controls { gap: 12px; padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px)); }
  #local-video { bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
  .settings-menu { bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
}

/* --- Auto-hide controls ---
 * Uses opacity (not visibility) so the accessibility tree is preserved:
 * focusin on a button inside #call-controls still fires and triggers
 * showControls() synchronously, preventing the "tab lands on invisible
 * button" race. The safety-number-bar is intentionally NOT in the
 * auto-hide selector list — it must remain visible at all times as a
 * persistent trust signal.
 *
 * Asymmetric transition: show is instant (0ms) so a focus ring is crisp
 * the instant focus lands; hide fades over 300ms. getComputedStyle
 * multiplies parent opacity with child opacity during transitions, so
 * without the 0ms show, a focus ring would inherit the fade.
 */
#call-controls {
  transition: opacity 300ms ease;
}
#videos:not(.controls-hidden) #call-controls {
  transition: opacity 0ms;
}
#videos.controls-hidden #call-controls {
  opacity: 0;
  pointer-events: none;
}
#videos.controls-hidden #local-video {
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
}
#videos.controls-hidden .settings-menu {
  display: none;
}

/* --- Settings menu --- */
.settings-menu {
  display: none;
  position: absolute;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 860;
  background: rgba(20, 20, 40, 0.9);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: 12px;
  padding: 8px 0;
  min-width: 200px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.5);
  border: 1px solid rgba(255,255,255,0.1);
}
.settings-menu.open {
  display: block;
}
.settings-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  color: #e0e0e0;
  font-size: 14px;
  cursor: pointer;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
}
.settings-menu-item:hover {
  background: rgba(255,255,255,0.1);
}
.settings-menu-item:active {
  background: rgba(255,255,255,0.15);
}
.settings-menu-item svg {
  width: 18px;
  height: 18px;
  color: #aaa;
  flex-shrink: 0;
}

/* --- Settings gear button --- */
.ctrl-btn-settings {
  background: rgba(255,255,255,0.1);
}

/* --- Hover states (pointer devices only) --- */
@media (hover: hover) {
  .ctrl-btn:hover { background: rgba(255,255,255,0.25); }
  .ctrl-btn.muted:hover { background: rgba(255,255,255,0.45); }
  .ctrl-btn-end:hover { background: #FF453A; }
}


/* --- Always-visible End Call button ---
 * #btn-hangup is structurally a sibling of #call-controls inside
 * #videos (see Phase 2 HTML change). The .ctrl-btn-end-fixed class
 * anchors it to the bottom-CENTER of the video area (FaceTime/Meet
 * pattern) so the user always has a way out of a call, even while
 * controls are auto-hidden. The button is deliberately NOT a child of
 * #call-controls so future auto-hide changes cannot accidentally hide
 * it. Bottom-center placement (rather than bottom-right) avoids the
 * geometric collision with the PiP local video default anchor and is
 * reachable by either thumb on a one-handed hold.
 */
#btn-hangup.ctrl-btn-end-fixed {
  /* Bottom-center placement (FaceTime/Meet pattern) — sits above the
   * #call-controls row so it never collides with the PiP bottom-right
   * anchor, and is reachable by either thumb on any phone size. The
   * 84px bottom offset clears #call-controls (content ~16-68px from
   * the bottom of #videos) with ~16px of breathing room. */
  position: absolute;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 860;
  width: 64px;
  height: 64px;
  border-radius: 32px;
  background: #d9262e;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 2px 12px rgba(0,0,0,0.6);
  transition: background-color 0.15s ease, transform 0.1s ease;
}
#btn-hangup.ctrl-btn-end-fixed svg {
  width: 26px;
  height: 26px;
}
#btn-hangup.ctrl-btn-end-fixed:hover {
  background: #e73a41;
}
#btn-hangup.ctrl-btn-end-fixed:active {
  background: #b01f26;
  /* Preserve the translateX(-50%) centering while applying the press
   * feedback scale — compound transforms are applied right-to-left. */
  transform: translateX(-50%) scale(0.95);
}
#btn-hangup.ctrl-btn-end-fixed:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 0;
  box-shadow: 0 0 0 4px rgba(0,0,0,0.6);
}
@media (max-width: 380px) {
  #btn-hangup.ctrl-btn-end-fixed {
    /* Narrow phone: shrink to 56x56 and keep the centered placement
     * above the (tighter) control bar. */
    width: 56px;
    height: 56px;
    border-radius: 28px;
    bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  }
}
@media (max-height: 500px) {
  #btn-hangup.ctrl-btn-end-fixed {
    /* Short landscape: 56x48 pill, centered, above the compact
     * control bar (padding 10px + 44px btn = ~64px). */
    width: 56px;
    height: 48px;
    border-radius: 24px;
    bottom: calc(68px + env(safe-area-inset-bottom, 0px));
  }
  #btn-hangup.ctrl-btn-end-fixed svg {
    width: 22px;
    height: 22px;
  }
}

/* --- Persistent PiP status badges ---
 * The local PiP video shows a mute badge and a camera-off badge
 * anchored to its top-left and top-right corners so the local user
 * always has an unambiguous view of their own state. The badges are
 * siblings of #local-video inside #videos (Phase 2 HTML). pip-drag.js
 * writes CSS custom properties --pip-x and --pip-y on #videos whenever
 * the PiP is dragged so the badges track the video without per-frame
 * JS updates to three elements.
 */
#videos {
  /* Defaults match the #local-video initial absolute position
   * (right/bottom corner). pip-drag.js overrides these when the user
   * drags the PiP. Units are device pixels (px) or CSS keywords like
   * "auto" — JS writes them as strings. */
  --pip-x: auto;
  --pip-y: auto;
}
.pip-badge {
  position: absolute;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #d9262e;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  z-index: 810;
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
  pointer-events: none;
}
.pip-badge svg {
  width: 16px;
  height: 16px;
}
/* Both badges default to hidden; JS (ui.js toggleMute/toggleCamera)
 * flips display to "flex" when the corresponding state is active. */
.pip-badge-mute,
.pip-badge-camera {
  display: none;
}
/* Badges are positioned against the PiP corners. When the PiP is in
 * its default position (no drag yet), --pip-x and --pip-y are "auto"
 * and the badges fall back to the same anchor as #local-video. When
 * pip-drag.js writes pixel values, the badges track the dragged PiP.
 * Offsets place the badges just inside the top corners of the PiP. */
.pip-badge-mute {
  /* Top-left corner of the PiP */
  left: var(--pip-badge-mute-left, auto);
  top: var(--pip-badge-mute-top, auto);
}
.pip-badge-camera {
  /* Top-right corner of the PiP */
  left: var(--pip-badge-camera-left, auto);
  top: var(--pip-badge-camera-top, auto);
  right: var(--pip-badge-camera-right, calc(20px + env(safe-area-inset-right, 0px)));
}
.pip-badge-mute.visible,
.pip-badge-camera.visible {
  display: flex;
}

/* --- Auto-hide first-run hint toast ---
 * Shown once per browser (localStorage key eagleeye.autohide.seen) on
 * the first hideControls() call so new users know the controls will
 * return on interaction. Class-based fade only — no inline style.
 */
.autohide-hint {
  display: none;
  position: absolute;
  bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 870;
  padding: 8px 16px;
  border-radius: 20px;
  background: rgba(0,0,0,0.75);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #ffffff;
  font-size: 13px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  box-shadow: 0 2px 12px rgba(0,0,0,0.5);
}
.autohide-hint.visible {
  display: block;
  opacity: 1;
}

/* --- Screen-reader-only live region utility ---
 * Reserved for future aria-live announcements (recording state,
 * verification result, connection transitions). Visually hidden but
 * present in the accessibility tree. */
.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;
}

/* --- Reduced motion ---
 * Respect the user's prefers-reduced-motion preference by removing
 * transitions on all in-call UI elements that animate. State changes
 * remain functionally correct — they just happen instantly. This
 * covers vestibular-disorder accessibility (WCAG 2.3.3) and also
 * helps users on low-end devices where animations cause jank during
 * video calls. */
@media (prefers-reduced-motion: reduce) {
  #call-controls,
  #videos:not(.controls-hidden) #call-controls,
  .safety-number-bar,
  .settings-menu,
  #local-video,
  .autohide-hint,
  .transport-tooltip,
  .connection-badge,
  #btn-hangup.ctrl-btn-end-fixed {
    transition: none !important;
  }
  .recording-dot {
    animation: none !important;
  }
}
