/* =========================================================================
   WolfsOfChat — css/call.css
   The full-screen CALL surface (F3 voice / F4 video). Fullscreen remote
   video, a draggable rounded picture-in-picture self-view, a floating glass
   control bar, and the ringing / connecting / in-call / ended states.

   DEPENDS ON css/theme.css (loaded FIRST in index.html). Consumes ONLY the
   semantic tokens declared there and NEVER invents a color/size:
     surfaces  --bg --surface --surface-raised --scrim
     text      --text-primary --text-secondary --text-tertiary --text-on-accent
     accent    --accent --accent-press
     status    --success (accept/green #0ecb81) --danger (hangup/decline)
     brand     violet --accent(#9061f9)  gold --warning(#d4a72c)
     layout    --tap-target --avatar-size --radius-* --z-modal …
     motion    --motion-* --ease-*
   Every var() carries a fallback IDENTICAL to the theme.css dark value, so a
   token rename during parallel builds degrades gracefully — the token is
   still the source of truth, which is what lets data-theme="light" re-skin
   this surface with zero edits here.

   OWNERSHIP: call-ui.js mounts a .call-screen and toggles the state modifier
   classes below (--audio/--video · --outgoing/--incoming/--connecting/
   --in-call/--ended). This file styles those states; it holds NO logic.

   MOTION DISCIPLINE (matches app.css §11 PIN-shake rule): every ringing /
   pulse / breathe / entrance animation is collapsed to a no-op inside the
   single prefers-reduced-motion block at the bottom. Motion is decoration,
   never function — a reduced-motion user still sees every state, just static.

   HARD LAYOUT RULE (inherited): the call surface lives inside #app — the
   phone frame with overflow:hidden. Nothing here may cause horizontal body
   scroll; the remote video and PiP are clipped to the frame.
   ========================================================================= */

/* ------------------------------------------------------------------ *
 * 1. Call surface container + per-state background
 *    Absolutely fills the phone frame and sits above the chat chrome
 *    (appbar / composer) so a live call fully owns the viewport.
 * ------------------------------------------------------------------ */
.call-screen {
  /* Component-local sizing knobs (not shared design tokens — call-only). */
  --call-btn-size: 58px;          /* secondary controls (mute / camera)  */
  --call-btn-size-primary: 66px;  /* accept / decline / hangup           */
  --pip-width: 104px;             /* self-view PiP (portrait ~3:4)        */

  position: absolute;
  inset: 0;
  z-index: var(--z-modal, 110);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--text-primary, #eaecef);
  background: var(--bg, #050508);
  /* Native feel: no blue tap flash, no accidental text selection on drag. */
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  /* Entrance: rise + fade (no-op under reduced motion). */
  animation: call-enter var(--motion-base, 220ms)
    var(--ease-decel, cubic-bezier(0, 0, 0.2, 1)) both;
}

/* Audio calls have no remote video — paint a calm violet/steel bloom so the
   surface never reads as an empty black rectangle. */
.call-screen--audio {
  background:
    radial-gradient(ellipse 620px 520px at 50% 22%,
      rgba(144, 97, 249, 0.22) 0%, transparent 62%),
    radial-gradient(ellipse 520px 640px at 50% 118%,
      rgba(11, 14, 17, 0.9) 0%, transparent 60%),
    var(--bg, #050508);
}

/* Video calls: the remote fills the frame, so keep the base pure black to
   avoid a colored seam behind object-fit:cover letterboxing. */
.call-screen--video { background: #000; }

/* Ended: gently dim the whole surface while call-ui shows the summary and
   schedules its own unmount. */
.call-screen--ended { animation: call-ended-dim var(--motion-slow, 320ms)
    var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1)) both; }

/* ------------------------------------------------------------------ *
 * 2. Remote video (fullscreen) + legibility scrims
 *    Out of flow (absolute) so the flex column below only lays out the
 *    info stage + control bar; the video floats edge-to-edge under them,
 *    covering the notch/safe areas by design.
 * ------------------------------------------------------------------ */
.call-screen__remote {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
  /* Remote is the OTHER party — never mirrored (self-view is, see §4). */
}
/* Hide the video element entirely on audio calls (the stage/avatar shows). */
.call-screen--audio .call-screen__remote { display: none; }

/* Top + bottom gradient scrims so the caller name and controls stay legible
   over a bright video frame. Pointer-inert; painted above the video only. */
.call-screen__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      rgba(3, 4, 8, 0.55) 0%, transparent 26%),
    linear-gradient(to top,
      rgba(3, 4, 8, 0.72) 0%, transparent 34%);
}
/* Audio calls carry their own bloom — no video to scrim over. */
.call-screen--audio .call-screen__scrim { display: none; }

/* ------------------------------------------------------------------ *
 * 3. Info stage — big avatar, caller name, status / timer
 *    Flex-grows to fill the space above the control bar. Centered for
 *    audio + ringing; call-ui pins it to the top for a connected video call.
 * ------------------------------------------------------------------ */
.call-screen__stage {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3, 12px);
  text-align: center;
  padding: var(--sp-6, 24px) var(--sp-5, 20px) var(--sp-4, 16px);
  padding-top: calc(env(safe-area-inset-top, 0px) + var(--sp-8, 40px));
}

/* Connected video call: info drops to a compact top strip so the remote
   video is unobstructed; the avatar is redundant (their face is on screen). */
.call-screen--video.call-screen--in-call .call-screen__stage {
  flex: 0 0 auto;
  justify-content: flex-start;
  gap: var(--sp-1, 4px);
  padding-bottom: 0;
}
.call-screen--video.call-screen--in-call .call-screen__avatar { display: none; }

.call-screen__avatar {
  width: 112px;
  height: 112px;
  border-radius: var(--radius-full, 999px);
  display: grid;
  place-items: center;
  font-size: var(--fs-3xl, 34px);
  font-weight: var(--fw-semibold, 600);
  color: var(--avatar-monogram, #0b0e11);   /* dark monogram on tinted fill */
  /* Fallback tint if call-ui doesn't set an inline avatarColor background. */
  background: var(--accent, #9061f9);
  box-shadow: var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.38));
}

.call-screen__name {
  font-size: var(--fs-xl, 22px);
  font-weight: var(--fw-semibold, 600);
  letter-spacing: var(--ls-tight, -0.01em);
  color: var(--text-primary, #eaecef);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.call-screen__status {
  font-size: var(--fs-base, 15px);
  font-weight: var(--fw-medium, 500);
  color: var(--text-secondary, #b7bdc6);
  letter-spacing: var(--ls-wide, 0.02em);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
/* Ringing / connecting: breathe the status line so the wait feels alive. */
.call-screen--outgoing .call-screen__status,
.call-screen--incoming .call-screen__status,
.call-screen--connecting .call-screen__status {
  animation: call-breathe 1.8s var(--ease-standard, ease-in-out) infinite;
}
/* The live-call timer reads as monospace tabular so digits don't jitter. */
.call-screen--in-call .call-screen__status,
.call-screen__timer {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: var(--text-primary, #eaecef);
  animation: none;
}
/* Ended summary reveal. */
.call-screen--ended .call-screen__status {
  color: var(--text-tertiary, #8a93a3);
  animation: call-fade-up var(--motion-base, 220ms)
    var(--ease-decel, cubic-bezier(0, 0, 0.2, 1)) both;
}

/* ------------------------------------------------------------------ *
 * 4. Picture-in-picture self-view (F4) — draggable, rounded
 *    Absolutely positioned; call-ui.js moves it by writing an inline
 *    transform/offset while .is-dragging suppresses the snap transition.
 *    touch-action:none keeps a touch-drag from scrolling the page.
 * ------------------------------------------------------------------ */
.pip-self {
  position: absolute;
  z-index: 3;
  top: calc(env(safe-area-inset-top, 0px) + var(--sp-4, 16px));
  right: var(--sp-4, 16px);
  width: var(--pip-width, 104px);
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg, 16px);
  overflow: hidden;
  background: var(--surface-sunken, #0b0e11);
  border: 1px solid var(--border-strong, rgba(255, 255, 255, 0.10));
  box-shadow: var(--shadow-3, 0 10px 28px rgba(0, 0, 0, 0.46));
  cursor: grab;
  touch-action: none;         /* drag, don't scroll */
  will-change: transform;
  /* Smooth snap when released; killed mid-drag by .is-dragging below. */
  transition: box-shadow var(--motion-fast, 140ms) var(--ease-standard, ease),
              transform var(--motion-base, 220ms)
                var(--ease-emphasized, cubic-bezier(0.2, 0, 0, 1));
}
.pip-self.is-dragging {
  cursor: grabbing;
  transition: none;           /* follow the finger 1:1 */
  box-shadow: var(--shadow-3, 0 10px 28px rgba(0, 0, 0, 0.55));
}
/* The self stream is mirrored — front-camera convention. */
.pip-self video,
.pip-self__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scaleX(-1);
  background: var(--surface-sunken, #0b0e11);
}
/* Camera off: the video goes blank — show a soft placeholder instead. */
.call-screen--video:not(.call-screen--camera-on) .pip-self {
  display: none;
}
/* Audio call: never show a self-view. */
.call-screen--audio .pip-self { display: none; }

/* ------------------------------------------------------------------ *
 * 5. Control bar — floating glass row pinned to the bottom
 * ------------------------------------------------------------------ */
.call-controls {
  position: relative;
  z-index: 4;
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: var(--sp-6, 24px);
  padding: var(--sp-5, 20px) var(--sp-5, 20px)
    calc(env(safe-area-inset-bottom, 0px) + var(--sp-6, 24px));
  /* Entrance: slide up from the bottom edge (no-op under reduced motion). */
  animation: call-controls-in var(--motion-slow, 320ms)
    var(--ease-decel, cubic-bezier(0, 0, 0.2, 1)) both;
}
/* Incoming: two big answers pushed to the edges (decline ⟷ accept). */
.call-screen--incoming .call-controls {
  justify-content: space-between;
  padding-left: var(--sp-8, 40px);
  padding-right: var(--sp-8, 40px);
}

/* Optional column wrapper: <span class="call-control"><button …><label…></span>
   so a control can carry a caption under it. Direct .call-btn children of
   .call-controls also lay out fine without this wrapper. */
.call-control {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2, 8px);
}
.call-btn__label {
  font-size: var(--fs-xs, 11px);
  font-weight: var(--fw-medium, 500);
  color: var(--text-secondary, #b7bdc6);
  letter-spacing: var(--ls-wide, 0.02em);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

/* ------------------------------------------------------------------ *
 * 6. Control buttons — circular, glass by default; colored for the
 *    call-decision actions (accept green / decline + hangup red).
 * ------------------------------------------------------------------ */
.call-btn {
  flex: 0 0 auto;
  width: var(--call-btn-size, 58px);
  height: var(--call-btn-size, 58px);
  min-width: var(--tap-target, 44px);
  min-height: var(--tap-target, 44px);
  display: grid;
  place-items: center;
  border-radius: var(--radius-full, 999px);
  color: var(--text-on-accent, #fff);
  /* Frosted glass so it reads over both video and the audio bloom. */
  background: rgba(255, 255, 255, 0.13);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: var(--shadow-1, 0 1px 2px rgba(0, 0, 0, 0.30));
  transition:
    background-color var(--motion-fast, 140ms) var(--ease-standard, ease),
    transform var(--motion-instant, 80ms) var(--ease-standard, ease);
}
.call-btn:active { transform: scale(0.92); }
.call-btn svg {
  width: 26px;
  height: 26px;
  display: block;
  pointer-events: none;   /* clicks land on the button, not the icon */
}

/* Toggle ON (muted mic / camera off): invert to a solid light chip — the
   established "this modifier is engaged" affordance. */
.call-btn.is-active,
.call-btn--muted,
.call-btn.is-on {
  background: var(--text-primary, #eaecef);
  color: var(--bg, #050508);
}

/* Primary decision buttons are larger and fully colored. */
.call-btn--accept,
.call-btn--decline,
.call-btn--hangup {
  width: var(--call-btn-size-primary, 66px);
  height: var(--call-btn-size-primary, 66px);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.38));
}

/* Accept = green (#0ecb81). */
.call-btn--accept {
  background: var(--success, #0ecb81);
  color: var(--text-on-accent, #fff);
}
.call-btn--accept:active { background: #0bb673; }

/* Decline + hangup = danger red. */
.call-btn--decline,
.call-btn--hangup {
  background: var(--danger, #f6465d);
  color: var(--danger-text, #fff);
}
.call-btn--decline:active,
.call-btn--hangup:active { background: var(--danger-press, #d63a4f); }

/* Hangup ends an active call — a hair heavier presence than a control. */
.call-btn--hangup { box-shadow: 0 6px 18px rgba(246, 70, 93, 0.42); }

/* Incoming: pulse a green halo around ACCEPT so the answer is obvious. */
.call-screen--incoming .call-btn--accept {
  animation: call-accept-pulse 1.6s var(--ease-standard, ease-out) infinite;
}

/* ------------------------------------------------------------------ *
 * 7. Keyframes (ringing / connecting / entrances / ended)
 *    All collapsed by the reduced-motion block in §8.
 * ------------------------------------------------------------------ */
@keyframes call-enter {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes call-controls-in {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes call-fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Status line "breathing" while ringing / connecting. */
@keyframes call-breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}
/* Expanding green ring on the incoming ACCEPT button. */
@keyframes call-accept-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(14, 203, 129, 0.50); }
  70%  { box-shadow: 0 0 0 20px rgba(14, 203, 129, 0); }
  100% { box-shadow: 0 0 0 0 rgba(14, 203, 129, 0); }
}
/* Ringing avatar halo (outgoing + incoming) — a soft violet pulse. */
.call-screen--outgoing .call-screen__avatar,
.call-screen--incoming .call-screen__avatar {
  animation: call-avatar-pulse 1.8s var(--ease-standard, ease-out) infinite;
}
@keyframes call-avatar-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(144, 97, 249, 0.45),
                     var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.38)); }
  70%  { box-shadow: 0 0 0 22px rgba(144, 97, 249, 0),
                     var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.38)); }
  100% { box-shadow: 0 0 0 0 rgba(144, 97, 249, 0),
                     var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.38)); }
}
@keyframes call-ended-dim {
  from { opacity: 1; }
  to   { opacity: 0.9; }
}

/* ------------------------------------------------------------------ *
 * 8. Reduced motion — collapse every ringing / pulse / entrance to a
 *    no-op (mirrors app.css §11). Full function, zero motion: the accept
 *    halo, avatar pulse, status breathe, slide-ups and dim all freeze at
 *    their resting frame; :active press-scale is neutralized too.
 * ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .call-screen,
  .call-screen *,
  .call-screen *::before,
  .call-screen *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .call-screen,
  .call-controls,
  .call-screen__status,
  .call-screen__avatar,
  .call-btn--accept {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .call-btn:active,
  .pip-self:active { transform: none; }
}
