/* Video Interface Styles - Light Theme */

/* Backdrop container - full screen behind all content */
.backdrop-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  z-index: -1; /* Behind all content */
  pointer-events: none;
  background: transparent; /* Transparent - let backdrops handle visuals */
}

/* Subtle frosted glass overlay on top of backdrops */
.backdrop-container::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  z-index: 1;
  pointer-events: none;
}

.backdrop-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: opacity 1000ms ease-in-out;
  will-change: opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Scoped CSS reset for video interface only */
.video-container * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

/* Preserve character sheet styling */
.character-container * {
  box-sizing: border-box; /* Keep this for proper sizing */
}

/* Override body centering for video interface */
body.video-mode {
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  margin: 0;
  height: 100vh;
  overflow: hidden;
  background: #f8f9fa;
}

body.video-mode .app {
  max-width: none;
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
}

/* Main split-screen container */
.main-container {
  display: flex;
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
  gap: 0; /* Remove gap between sheet and video */
}

/* Character sheet container - fixed left side */
.character-container {
  flex: 0 0 400px;
  height: 100vh;
  overflow-y: auto;
  background: rgba(41, 145, 222, 0.65);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-sizing: border-box;
  margin: 0;
  padding: 20px;
  padding-bottom: 90px; /* Space for fixed video controls at bottom */
  position: relative;
  z-index: auto; /* Don't create stacking context */
  border-right: 1px solid rgba(255, 255, 255, 0.8); /* White border on right */
}

/* Ensure character container maintains scrolling during screen sharing */
.video-container.screen-sharing-mode ~ .character-container,
.main-container .character-container {
  overflow-y: auto !important;
  height: 100vh !important;
  position: relative !important;
  z-index: 10 !important; /* Higher than screen sharing overlays */
  pointer-events: auto !important;
}

/* Ensure character sheet content remains interactive */
.character-container * {
  pointer-events: auto;
}

/* Make sure screen sharing overlays don't block character container interactions */
.screen-sharing-main,
.screen-sharing-participants {
  pointer-events: auto;
}

/* Prevent screen sharing backgrounds from interfering with character container */
.video-container.screen-sharing-mode .character-container {
  isolation: isolate;
}

/* Video container - takes remaining space */
.video-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: transparent; /* Remove default background so generated backdrop shows */
  position: relative;
  margin: 0;
  padding: 0;
  border: none;
  border-left: none;
}

/* Remove the blurred backdrop pseudo-elements - BackdropManager handles this */
/* These are commented out so generated backdrops from QuestAI can show through
.video-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0 !important;
  right: 0;
  bottom: 0;
  background: url('../assets/smallername.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(100px);
  z-index: -1;
}

.video-container::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0 !important;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(50px);
  z-index: 0;
}
*/

/* Facilitator full-screen mode */
.video-container.facilitator-mode {
  width: 100%;
  height: 100vh;
  isolation: isolate; /* contain blending/compositing to the facilitator container */
}

/* Force permanent layer promotion for facilitator tiles/grid */
.video-container.facilitator-mode,
.video-container.facilitator-mode .participants-grid,
.video-container.facilitator-mode .participant,
.video-container.facilitator-mode .participant video {
  will-change: transform, opacity;
  transform: translateZ(0);
  backface-visibility: hidden;
  contain: paint;
}

/* Reduce paint-heavy effects that destabilize layers in facilitator mode */
.video-container.facilitator-mode .participant {
  box-shadow: none;
}
.video-container.facilitator-mode .participant:hover {
  transform: none;       /* no hover-scale: prevents re-rasterization */
  box-shadow: none;      /* keep hover cheap */
  border-color: #4a9eff; /* still provide a hover affordance */
}

/* Disable heavy blur layers for facilitator or when explicitly requested */
.video-container.no-blur {
  background: transparent;
}
.video-container.no-blur::before,
.video-container.no-blur::after {
  display: none !important;
}

/* Screen sharing mode styles */
.video-container.screen-sharing-mode {
  position: relative;
}

.screen-sharing-main {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: url('../assets/smallername.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  position: relative;
  z-index: 5; /* Lower than character container */
  pointer-events: auto;
}

.screen-sharing-main::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: url('../assets/smallername.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(100px);
  z-index: -1;
}

/* Overlay participants on screen share */
.screen-sharing-participants {
  position: absolute;
  top: 20px;
  bottom: 100px;
  right: 20px;
  width: 280px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 6; /* Lower than character container */
  pointer-events: auto;
}

.screen-sharing-participants::-webkit-scrollbar {
  width: 6px;
}

.screen-sharing-participants::-webkit-scrollbar-track {
  background: transparent;
}

.screen-sharing-participants::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.3);
  border-radius: 3px;
}

.screen-sharing-participants::-webkit-scrollbar-thumb:hover {
  background: rgba(255,255,255,0.5);
}

.screen-sharing-participant {
  aspect-ratio: 16/9;
  background: #111;
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid rgba(255,255,255,0.3);
  transition: all 0.3s ease;
  position: relative;
  min-height: 100px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.5);
  flex-shrink: 0;
}

.screen-sharing-participant:hover {
  border-color: #4a9eff;
  transform: scale(1.02);
}

.screen-sharing-participant.local {
  border-color: #28a745;
}

.screen-sharing-participant video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.screen-sharing-participant.local video {
  transform: scaleX(-1);
}

.screen-sharing-participant .participant-name {
  position: absolute;
  bottom: 4px;
  left: 4px;
  right: 4px;
  background: rgba(0, 0, 0, 0.85);
  color: white;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Portrait overlay for screen sharing participants */
.screen-sharing-participant .participant-portrait {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 40px;
  height: 40px;
  z-index: 5;
  pointer-events: none;
}

.screen-sharing-participant .participant-portrait-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 2px solid #2991de;
  object-fit: cover;
  background: #6cace4;
}

.screen-share-video {
  flex: 1;
  display: flex;
  align-items: center;
  flex-direction: column; /* vertical stack so justify-content controls bottom alignment */
  justify-content: center;
  position: relative;
  z-index: 5;
  background: transparent;
}

.screen-share-video video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 6;
}

/* Improve GPU stability to mitigate artifacts */
.participant video,
.screen-share-video video {
  will-change: transform;
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Ensure proper z-index layering for screen sharing */
.screen-sharing-mode .screen-share-video {
  z-index: 5;
}

.screen-sharing-mode .screen-sharing-participants {
  z-index: 6;
}

/* Character container should always be on top for interactions */
.main-container .character-container {
  z-index: 10 !important;
  isolation: isolate;
}

/* Video header - Hidden to remove gray bar */
.video-header {
  display: none;
}

.room-info {
  display: flex;
  align-items: center;
  gap: 20px;
}

.room-code {
  font-size: 14px;
  font-weight: 600;
  color: #495057;
  background: #e9ecef;
  padding: 6px 12px;
  border-radius: 20px;
  border: 1px solid #ced4da;
}

/* Hide connection status bar and video-specific gray elements only */
.video-container .connection-status,
.video-container .room-header,
.video-container .header-bar,
.video-container .status-bar,
.video-container .video-status,
.video-container .room-status,
.video-container .livekit-header,
.video-container .top-bar,
.video-container .navigation-bar,
.video-container .toolbar,
.video-container .menu-bar,
.video-container .title-bar,
.video-container .nav-bar,
.video-container .breadcrumb {
  display: none !important;
}

/* CRITICAL: Hide old dice-controls-container (bottom-right UI from non-video mode) */
body.video-mode #dice-controls-container {
  display: none !important;
  position: static !important;
  pointer-events: none !important;
}

/* Hide old timer display SVG circles in character sheet during video mode */
body.video-mode #timer-display {
  display: none !important;
}

/* Remove all gray backgrounds and elements */
/* Make body transparent so BackdropManager's backdrop shows through */
body.video-mode {
  background: transparent !important;
}

/* Force hide any remaining gray bars - but not in character sheet */
.video-container div[style*="background: #"], 
.video-container div[style*="background-color: #"],
.video-container .bg-gray,
.video-container .gray-bar,
.video-container .gray-header,
.video-container .gray-menu,
.bg-gray:not(.character-container *),
.gray-bar:not(.character-container *),
.gray-header:not(.character-container *),
.gray-menu:not(.character-container *) {
  display: none !important;
}

/* Dice and timer backdrop at top */
.dice-and-timer-container {
  position: fixed;
  top: 0;
  left: 400px; /* Start after character container */
  right: 0;
  height: auto; /* QUE-520: flex to fit the tallest child — threat cards grow when a name label wraps below the portrait */
  min-height: clamp(60px, 10vh, 100px); /* Floor tracks the original 10vh-clamped bar height, so the no-threat bar stays flush with the video grid (top:10vh) and toast offsets instead of collapsing to 60px */
  max-height: 100px; /* Ceiling: threat card tops out ~90px (64px portrait + 3px gap + 23px 2-line label), so this never clips and preserves the <=100px contract the video grid (top:10vh) and toast offsets rely on */
  background: rgba(41, 145, 222, 0.65); /* Blue with transparency */
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.8); /* White border on bottom */
  z-index: 50; /* Same level as bottom backdrop */
  pointer-events: auto; /* Allow interaction with dice */
  display: flex;
  align-items: center;
  padding: 0 20px;
  gap: 15px;
}

/* For facilitators, dice bar spans full width from left edge */
.video-container.facilitator-mode .dice-and-timer-container {
  left: 0 !important;
}

/* Dice area - flexes to fill available space on left */
.dice-area {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: flex-start;
  align-self: stretch; /* QUE-520: the bar is now height:auto, so height:100% here would resolve to auto and collapse dice-area to its ~10px padding — crushing the absolutely-positioned .objectives-strip (inset:0) into a thin band. Stretch to the bar's used cross-axis height instead so the strip fills the full bar. (Must NOT also set height:100% — a percentage height would keep align-self:stretch from applying.) */
  padding: 5px 0;
  min-width: 0; /* Allow flexbox to shrink below content size */
}

/* Dice slots row wrapper — inline on desktop, separate row on mobile */
.dice-slots-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

/* Individual dice slot - semi-transparent white bg with outline */
/* AI-managed: no click interactions */
.dice-slot {
  position: relative;
  background: rgba(255, 255, 255, 0.5);
  border: 2px solid rgba(255, 255, 255, 0.8);
  border-radius: 6px;
  cursor: default !important; /* Changed from pointer - AI controls dice */
  pointer-events: none; /* Disable all interactions */
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-sizing: border-box;
}

/* Responsive dice sizing based on difficulty */
.dice-area[data-difficulty="1"] .dice-slot,
.dice-area[data-difficulty="2"] .dice-slot {
  width: 45px;
  height: 45px;
}

.dice-area[data-difficulty="3"] .dice-slot,
.dice-area[data-difficulty="4"] .dice-slot,
.dice-area[data-difficulty="5"] .dice-slot {
  width: 40px;
  height: 40px;
}

.dice-area[data-difficulty="6"] .dice-slot,
.dice-area[data-difficulty="7"] .dice-slot,
.dice-area[data-difficulty="8"] .dice-slot {
  width: 35px;
  height: 35px;
}

.dice-area[data-difficulty="9"] .dice-slot,
.dice-area[data-difficulty="10"] .dice-slot,
.dice-area[data-difficulty="11"] .dice-slot,
.dice-area[data-difficulty="12"] .dice-slot {
  width: 32px;
  height: 32px;
}

.dice-area[data-difficulty="13"] .dice-slot,
.dice-area[data-difficulty="14"] .dice-slot,
.dice-area[data-difficulty="15"] .dice-slot {
  width: 28px;
  height: 28px;
}

.dice-area[data-difficulty="16"] .dice-slot,
.dice-area[data-difficulty="17"] .dice-slot,
.dice-area[data-difficulty="18"] .dice-slot,
.dice-area[data-difficulty="19"] .dice-slot,
.dice-area[data-difficulty="20"] .dice-slot {
  width: 25px;
  height: 25px;
}

/* Dice slot hover effect */
/* REMOVED: Hover state - dice slots are now AI-managed and non-interactive */
.dice-slot:hover {
  /* No hover effects - AI controls dice commitment */
}

/* Claimed dice slot */
.dice-slot.claimed {
  border-color: #28a745;
  background: rgba(40, 167, 69, 0.2);
  cursor: default;
}

/* Pool participant portrait stack — overlapping circles */
.pool-participant-stack {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  margin-right: 14px;
  padding: 2px 14px 2px 0;
  border-right: 1px solid rgba(255, 255, 255, 0.9);
}

/* "See Why" — on-demand breakdown of what pushed the pool up or down.
   No toast, no auto-open: the affordance sits beside the pool and only opens
   on hover, focus or click. It is rendered only when difficulty.set carried
   factors, so an older Guide response looks exactly as it did before.

   MOUNT POINT — the button and the panel are SPLIT, and each half is where it
   is for a different reason:

   .risk-why (the button) is a CHILD of .dice-area, appended after the dice
   slots, so it reads as attached to the pool it explains. It cannot live after
   .dice-area: that element is `flex: 1`, so it absorbs all the free space in
   the bar and pushes any following sibling hard against the right edge.

   .risk-why-panel is a CHILD of the bar (.dice-and-timer-container on desktop,
   .mobile-game-hud on mobile) — NOT of .dice-area and NOT of .risk-why.
   .dice-area has `overflow: hidden` (see the objectives-strip block below) and
   is roughly one dice-row tall, so a panel hanging 80-120px below the button
   is clipped away inside it. Do not move the panel into .dice-area, and do not
   "fix" that by setting overflow: visible on .dice-area — that reopens the bug
   the rule was added for.

   Both hosts are already positioned (fixed / absolute), so the panel's
   `position: absolute` resolves against the bar. Its horizontal offset is
   written by _positionRiskWhyPanel, which centres it under the button and
   clamps it to the viewport; the `left: 0` below is only the fallback used
   before the first measurement.

   Colour rule (deliberate, do not invert): a factor that LOWERS risk shows a
   GREEN MINUS, a factor that RAISES risk shows a RED PLUS. The sign tracks the
   effect on the dice pool (fewer dice is better); the colour tracks whether it
   helps the party. A factor's weight is shown as repeated glyphs ("− −"), never
   as a digit. The only number in the panel is on the base-risk line at the
   top: the Guide's gut check of the situation alone, which the factors below
   then move up or down to the dice on screen. */
.risk-why {
  /* NOT a positioning context: the panel is mounted on the bar, not in here,
     so `position: relative` would be a lie about where it resolves. */
  flex-shrink: 0;
  display: flex;
  align-items: center;
  /* Extra left margin on top of .dice-area's 8px flex gap so the button reads
     as its own control instead of sitting flush against the dice pool
     (Asa, requested twice — give See Why more breathing room). */
  margin-left: 10px;
}

.risk-why-btn {
  /* Unlike every other pill in this file, this is a native <button> — reset
     UA appearance (Safari/iOS add their own chrome and padding on top of
     author styles) and center the label explicitly instead of relying on
     the browser's own (inconsistent, per-engine) button text centering. */
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 12px;
  color: #fff;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  padding: 5px 10px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s ease, border-color 0.2s ease;
  /* Center on cap-height + alphabetic baseline, not the font's full ascent/
     descent box. No-op where unsupported. */
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.risk-why-btn:hover {
  background: rgba(255, 255, 255, 0.24);
  border-color: rgba(255, 255, 255, 0.85);
}

.risk-why-btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* Fallback for browsers without :focus-visible — keyboard users must still
   see where they are. */
.risk-why-btn:focus {
  background: rgba(255, 255, 255, 0.24);
}

.risk-why-panel {
  position: absolute;
  /* Fallback placement only. _positionRiskWhyPanel overwrites top and left on
     every open, anchoring the panel to the button's measured position rather
     than to either edge of the bar. */
  top: calc(100% + 8px);
  left: 0;
  right: auto;
  z-index: 200;
  /* As wide as its longest line, so nothing wraps (Asa, 2026-09-25: "that
     see why box can be as wide as needed. it can extend"). Never wider than
     the viewport minus an 8px gutter on each side; the JS clamp handles the
     position. */
  min-width: min(220px, calc(100vw - 16px));
  width: max-content;
  /* Sentences read best at a paragraph width. */
  max-width: min(340px, calc(100vw - 16px));
  padding: 12px 14px;
  /* Blue receipt, white text (Asa, 2026-09-24: "white text, blue gradient
     panel"). Same hue as the app's --bg1/--bg2 blue, taken deeper so 13px
     white text stays above 4.5:1 contrast (the lighter #5BA3E5 is 2.7:1). */
  /* Lighter and nearly flat (Asa, 2026-09-25: "too dark"); white text stays
     at 4.5:1 or better across it. */
  background: linear-gradient(160deg, #3B79BA 0%, #3A78B8 100%);
  border: 2px solid rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.35);
  color: #fff;
}

.risk-why-panel[hidden] {
  display: none;
}

/* Base-risk line: "Base risk: Playing with fire  7". Sits above the factor
   list, separated by a hairline, so the receipt reads top-down: situation
   first, then what the party brings to it. */
.risk-why-base {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: #fff;
  font-size: 13px;
  line-height: 1.35;
  padding: 2px 0 6px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}

/* Aggregate special-moves line. A special move is a guaranteed die off the
   risk the factors produced, not another factor, so a heavier bar sits above
   it: everything above the bar evens out to at most one die, and each minus
   below it takes one die off that result (Asa, 2026-09-24). */
/* Nothing adjusted the risk: the Base Risk line is the whole panel, so it
   needs no divider under it. */
.risk-why-base:last-child {
  border-bottom: 0;
  margin-bottom: 0;
  padding-bottom: 2px;
}

/* Doubled class: .risk-why-item (later in this file) sets padding: 3px 0,
   which used to win and left the row touching the bar. */
.risk-why-moves.risk-why-item {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 2px solid rgba(255, 255, 255, 0.85);
}


/* Total line: "Risk  4". The dice on screen, restated under the receipt. */
.risk-why-total {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: #fff;
  font-size: 13px;
  line-height: 1.35;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
}

.risk-why-total-key {
  color: rgba(255, 255, 255, 0.85);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.risk-why-total-dice {
  margin-left: auto;
  padding-left: 12px;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.risk-why-base-key {
  color: rgba(255, 255, 255, 0.85);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.risk-why-base-label {
  font-weight: 600;
}

.risk-why-base-dice {
  margin-left: auto;
  padding-left: 12px;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.risk-why-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.risk-why-item {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #fff;
  font-size: 13px;
  line-height: 1.35;
  padding: 3px 0;
}

.risk-why-sign {
  /* One coloured dot per die the line moves the pool by (Asa, 2026-09-25:
     "no +s or -s. Red dots, green dots, gold dots."). Factor lines always
     carry one dot, so their labels line up; only the special-moves line under
     the bar can carry more. Fixed height so the dots sit on the label's
     centre line. */
  flex-shrink: 0;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 4px;
  height: 20px;
  min-width: 14px;
  font-size: 0;
  line-height: 0;
}

/* The dot. The character ("−" or "+") stays in the DOM, invisible, for copy
   and tests. The white ring carries the contrast against the blue panel (red
   and green alone are under 3:1 on it); the fill carries the meaning. */
.risk-why-glyph {
  flex-shrink: 0;
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  color: transparent;
  overflow: hidden;
}

/* A reason behind the Base Risk: a small neutral bullet, no dice meaning.
   Centred in the dot column so reason text lines up with the moves line. */
.risk-why-bullet {
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  margin-left: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
}

/* Special moves: gold, a different kind of die off than a factor's green
   (Asa, 2026-09-25). */
.risk-why-moves.risk-why-item--for .risk-why-glyph {
  /* A lit coin, not a flat amber: a flat yellow dot read like a caution
     light (Asa, 2026-09-25: "so it doesnt look like... a slow sign"). */
  background: radial-gradient(circle at 35% 30%, #FFF6C8 0%, #FFD24A 35%, #E0A000 70%, #A86E00 100%);
}

/* Trim the label's line box to cap height and baseline, so centring it on the
   dot centres the letters, not League Spartan's tall ascender space (text
   measured 2.3px high before this, 0.3px after). */
.risk-why-item .risk-why-text {
  text-box: trim-both cap alphabetic;
}

/* See Why as plain sentences (Asa, 2026-09-25, option 1): the situation and
   what it usually takes, what is in your favor and against you, where that
   lands, then each special move by name. Each sentence ends on its dice. */
.risk-why-panel .risk-why-line {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  color: #fff;
  font-size: 13.5px;
  line-height: 1.4;
}

.risk-why-panel .risk-why-line + .risk-why-line {
  margin-top: 6px;
}

.risk-why-panel .risk-why-line strong {
  font-weight: 700;
  font-size: inherit;
  margin: 0;
  padding: 0;
}

/* Inside a sentence, a factor and a move's text flow as words, not rows. */
.risk-why-panel .risk-why-line .risk-why-item,
.risk-why-panel .risk-why-line .risk-why-text {
  display: inline;
  padding: 0;
  text-box: normal;
}

.risk-why-factors--for .risk-why-factors-key {
  color: #B6F5CB;
}

.risk-why-factors--against .risk-why-factors-key {
  color: #FFC2C2;
}

/* Special moves: a hairline above the first one, gold dots, the move named. */
.risk-why-panel .risk-why-moves {
  display: flex;
  align-items: center;
  gap: 8px;
}

.risk-why-panel .risk-why-line:not(.risk-why-moves) + .risk-why-moves {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
}

.risk-why-moves .risk-why-glyph {
  background: radial-gradient(circle at 35% 30%, #FFF6C8 0%, #FFD24A 35%, #E0A000 70%, #A86E00 100%);
}

.risk-why-moves--raise .risk-why-glyph {
  background: #EF4444;
}

/* QUE-141: Push Luck divider — white vertical line separating the bonus die
   from the main dice pool. Mirrors the .pool-participant-stack border-right
   pattern so the bonus die reads as visually distinct from the original pool. */
.push-luck-divider {
  flex-shrink: 0;
  width: 1px;
  align-self: stretch;
  min-height: 24px;
  margin: 0 6px;
  background: rgba(255, 255, 255, 0.9);
  pointer-events: none;
}

.pool-participant-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2.5px solid #fff;
  background: rgba(41, 145, 222, 0.7);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}

.pool-participant-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  user-select: none;
  pointer-events: none;
}

.pool-participant-avatar span {
  font-size: 14px;
  font-weight: 700;
  color: #fff;
  user-select: none;
}

/* Legacy player portrait in dice slot (no longer rendered but kept for compat) */
.dice-player-portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
  user-select: none;
  pointer-events: none;
}

/* Player avatar/initial in dice (fallback when no portrait) */
.dice-player-indicator {
  font-size: 12px;
  font-weight: 700;
  color: white;
  text-align: center;
  user-select: none;
  pointer-events: none;
}

/* Dice value display (after roll) */
.dice-value {
  font-size: 18px;
  font-weight: 800;
  color: white;
  text-align: center;
  user-select: none;
  pointer-events: none;
}

/* QuestWorks logo watermark inside pending (not-yet-rolled) dice */
.dice-logo {
  width: 60%;
  height: 60%;
  opacity: 0.85;
  pointer-events: none;
  user-select: none;
}

/* QUE-143: Un-rolled slot state — used when the dice pool ended early (rolled a 1
   or 6 mid-pool) and remaining slots never got a value. Visually distinct from:
   - pending dice (favicon-logo, ~85% opacity)
   - rolling dice (pulsing pulse animation, brighter background)
   - rolled dice (color-coded result-N styles)
   The slot frame is preserved (positional layout) but dimmed; an em-dash in the
   center reads as "skipped/not rolled" rather than "missing dice". */
.dice-slot.unrolled {
  opacity: 0.35;
  background: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.4);
  border-style: dashed;
  box-shadow: none;
}

.dice-unrolled-mark {
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  color: rgba(255, 255, 255, 0.95);
  text-align: center;
  user-select: none;
  pointer-events: none;
}

/* Dice rolling animation — gentle pulse, no rotation (JS handles value changes) */
.dice-slot.rolling {
  animation: diceRoll 0.3s ease-in-out infinite;
  background: rgba(255, 255, 255, 0.3);
}

@keyframes diceRoll {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

@keyframes dicePop {
  0% { transform: scale(1); }
  40% { transform: scale(1.25); }
  100% { transform: scale(1); }
}

/* Dice result states */
.dice-slot.result-6 {
  background: rgba(40, 167, 69, 0.4);
  border-color: #28a745;
  box-shadow: 0 0 10px rgba(40, 167, 69, 0.6);
}

.dice-slot.result-1 {
  background: rgba(220, 53, 69, 0.4);
  border-color: #dc3545;
  box-shadow: 0 0 10px rgba(220, 53, 69, 0.6);
}

.dice-slot.result-4,
.dice-slot.result-5 {
  background: rgba(255, 193, 7, 0.3);
  border-color: #ffc107;
}

.dice-slot.result-2,
.dice-slot.result-3 {
  background: rgba(255, 152, 0, 0.3);
  border-color: #ff9800;
}

/* Dice row, next version (Asa, 2026-09-30, "Dice Row Next" prototype). Classes are set
   by DicePoolManager._diceView / _playRevealEffects; tiles are patched in place so
   these transitions and one-shot animations survive the 60 ms spin frames.
   - held:   the highest die so far wears a bright ring (numbers and colors stay)
   - beaten: rolled dice that are not the held die dim
   - dice not yet rolled shrink with distance (size set inline by the JS)
   - discarded: BAM (a 6 or a 1) or Stamp clears every other die at once
   - bam / stamp / pulse / pop: one-shot effects; the bar flashes behind them */
/* The 6 or 1 that ended the roll (stopper) is the deciding die too, so it looks
   exactly like the held die: same ring, same size (Asa, 2026-10-02). It is
   listed after the result-6/result-1 rules so the ring replaces their glow. */
.dice-slot.held,
.dice-slot.stopper {
  box-shadow: 0 0 0 2px #fff, 0 0 12px rgba(255, 255, 255, 0.7);
  transform: scale(1.08);
}

.dice-slot.beaten {
  opacity: 0.4;
}

.dice-area .dice-slot.discarded {
  width: 0 !important;
  height: 0 !important;
  min-width: 0 !important;
  min-height: 0 !important;
  border-width: 0 !important;
  /* Hide the discarded tile immediately. Its dimensions may still animate closed,
     but no border/background sliver can overlap the surviving BAM/Stamp die. */
  visibility: hidden;
  opacity: 0;
  margin-right: -8px; /* cancels the row gap, so the kept die closes up */
  transition: width 0.2s ease-in, height 0.2s ease-in, min-width 0.2s ease-in, min-height 0.2s ease-in,
    border-width 0.2s ease-in, margin 0.2s ease-in, opacity 0.12s ease-in;
}

.mobile-game-hud .dice-area .dice-slot.discarded {
  margin-right: -6px;
}

/* The phone row sits flush against the clipping edge; room for the ring. */
.mobile-game-hud .dice-slots-row {
  padding: 4px;
}

.dice-slot.pulse {
  animation: diceHeldPop 0.3s ease-out;
}

.dice-slot.pop {
  animation: dicePop 0.4s ease-out;
}

.dice-slot.bam {
  animation: diceBam 0.45s cubic-bezier(0.2, 1.6, 0.4, 1);
}

.dice-slot.stamp {
  animation: diceStamp 0.4s cubic-bezier(0.2, 1.5, 0.4, 1);
}

@keyframes diceHeldPop {
  0% { transform: scale(1.08); }
  40% { transform: scale(1.22); }
  100% { transform: scale(1.08); }
}

/* Peaks stay under 1.35x: .dice-area clips (overflow: hidden) and a 45px die
   fits a 60px bar up to about 1.33x. */
@keyframes diceBam {
  0% { transform: scale(1.35); }
  60% { transform: scale(0.9); }
  100% { transform: scale(1.08); }
}

@keyframes diceStamp {
  0% { transform: scale(1.3); }
  60% { transform: scale(0.95); }
  100% { transform: scale(1.08); }
}

/* Bar flash: an inset shadow paints over the bar's own background and under the
   dice, so it works on the desktop bar and the mobile HUD alike. */
.dice-flash-good { animation: diceFlashGood 0.6s ease-out; }
.dice-flash-bad { animation: diceFlashBad 0.6s ease-out; }
.dice-flash-soft-good { animation: diceFlashSoftGood 0.55s ease-out; }
.dice-flash-soft-bad { animation: diceFlashSoftBad 0.55s ease-out; }

@keyframes diceFlashGood {
  0% { box-shadow: inset 0 0 0 999px rgba(40, 167, 69, 0.75); }
  100% { box-shadow: inset 0 0 0 999px rgba(40, 167, 69, 0); }
}

@keyframes diceFlashBad {
  0% { box-shadow: inset 0 0 0 999px rgba(220, 53, 69, 0.75); }
  100% { box-shadow: inset 0 0 0 999px rgba(220, 53, 69, 0); }
}

@keyframes diceFlashSoftGood {
  0% { box-shadow: inset 0 0 0 999px rgba(255, 193, 7, 0.6); }
  100% { box-shadow: inset 0 0 0 999px rgba(255, 193, 7, 0); }
}

@keyframes diceFlashSoftBad {
  0% { box-shadow: inset 0 0 0 999px rgba(255, 152, 0, 0.6); }
  100% { box-shadow: inset 0 0 0 999px rgba(255, 152, 0, 0); }
}

/* Reduced motion: accessibility.css already cuts every animation to 0.01 ms, which
   still fires animationend, so the one-shot tile classes clear themselves. */
@media (prefers-reduced-motion: reduce) {
  .dice-flash-good,
  .dice-flash-bad,
  .dice-flash-soft-good,
  .dice-flash-soft-bad {
    animation: none;
  }

  .dice-area .dice-slot.discarded {
    transition: none;
  }
}

/* Timer area — stacks tension + portal timers vertically, right-aligned */
.timer-area {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex-shrink: 0;
  margin-left: auto;
  min-width: 140px;
}

/* Compact timer styles (used by LiveKit UI) */
.timer-compact {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
  font-weight: 600;
  color: white;
  white-space: nowrap;
}

.timer-compact-label {
  opacity: 0.9;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.timer-compact-value {
  font-size: 20px;
  font-weight: 700;
  padding: 4px 12px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.4);
  transition: all 0.3s ease;
  min-width: 60px;
  text-align: center;
}

/* Compact timer critical state (1-10 seconds) - pulsing */
.timer-compact.timer-critical .timer-compact-value {
  color: #ff3333;
  background: rgba(244, 67, 54, 0.3);
  border: 2px solid #ff3333;
  animation: compact-timer-pulse 0.4s ease-in-out infinite;
  box-shadow: 0 0 20px rgba(244, 67, 54, 0.8);
}

/* Compact timer at 0 - red but static (no pulse) */
.timer-compact.timer-zero .timer-compact-value {
  color: #ff3333;
  background: rgba(244, 67, 54, 0.3);
  border: 2px solid #ff3333;
  box-shadow: 0 0 15px rgba(244, 67, 54, 0.6);
}

@keyframes compact-timer-pulse {
  0%, 100% {
    transform: scale(1);
    box-shadow: 0 0 20px rgba(244, 67, 54, 0.8);
  }
  50% {
    transform: scale(1.1);
    box-shadow: 0 0 30px rgba(244, 67, 54, 1);
  }
}

/* Participants grid - Container for positioned tiles */
.participants-grid {
  position: fixed;
  top: 10vh; /* Start after dice panel */
  left: 400px; /* After character sheet */
  right: 0;
  bottom: 15vh; /* Above QuestAI panel */
  pointer-events: none; /* Allow clicks through to background */
  z-index: 1;
}

/* For facilitators, grid spans full width */
.video-container.facilitator-mode .participants-grid {
  left: 0 !important;
}

/* Blue frosted glass bar at bottom of video grid for QuestAI panel - REMOVED */
/*
.participants-grid::after {
  content: '';
  position: fixed;
  bottom: 0;
  left: 400px;
  right: 0;
  height: 90px;
  background: rgba(41, 145, 222, 0.55);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-top: 1px solid rgba(255, 255, 255, 0.8);
  z-index: 50;
  pointer-events: none;
}
*/

/* Participant video tiles - Compact and positioned */
.participant {
  position: absolute;
  width: 240px;
  height: 135px; /* 16:9 aspect ratio (240 / 16 * 9) */
  background: #111;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.3);
  transition: all 0.3s ease;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  pointer-events: auto; /* Re-enable clicks on tiles */
}

/* 1 Player: Upper right */
.participants-grid:has(.participant:nth-child(1):last-child) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

/* 2 Players: Upper right, upper left */
.participants-grid:has(.participant:nth-child(2):last-child) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(2):last-child) .participant:nth-child(2) {
  top: 20px;
  left: 20px;
}

/* 3 Players: Upper right, upper middle, upper left */
.participants-grid:has(.participant:nth-child(3):last-child) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(3):last-child) .participant:nth-child(2) {
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.participants-grid:has(.participant:nth-child(3):last-child) .participant:nth-child(3) {
  top: 20px;
  left: 20px;
}

/* 4 Players: Upper right, upper left, bottom right, bottom left */
.participants-grid:has(.participant:nth-child(4):last-child) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(4):last-child) .participant:nth-child(2) {
  top: 20px;
  left: 20px;
}

.participants-grid:has(.participant:nth-child(4):last-child) .participant:nth-child(3) {
  bottom: 40px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(4):last-child) .participant:nth-child(4) {
  bottom: 40px;
  left: 20px;
}

/* 5 Players: Upper right, upper middle, upper left, bottom right, bottom left */
.participants-grid:has(.participant:nth-child(5):last-child) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(5):last-child) .participant:nth-child(2) {
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.participants-grid:has(.participant:nth-child(5):last-child) .participant:nth-child(3) {
  top: 20px;
  left: 20px;
}

.participants-grid:has(.participant:nth-child(5):last-child) .participant:nth-child(4) {
  bottom: 40px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(5):last-child) .participant:nth-child(5) {
  bottom: 40px;
  left: 20px;
}

/* 6+ Players: Add bottom middle and continue pattern */
.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(1) {
  top: 20px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(2) {
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
}

.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(3) {
  top: 20px;
  left: 20px;
}

.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(4) {
  bottom: 40px;
  right: 20px;
}

.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(5) {
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
}

.participants-grid:has(.participant:nth-child(n+6)) .participant:nth-child(6) {
  bottom: 40px;
  left: 20px;
}

/* 7+ Players: Stack vertically on right side for overflow */
.participants-grid:has(.participant:nth-child(n+7)) .participant:nth-child(n+7) {
  top: 20px;
  right: 280px; /* Stack to left of first column */
  /* Calculate vertical offset based on index */
}

.participants-grid:has(.participant:nth-child(n+7)) .participant:nth-child(7) {
  top: 20px;
}

.participants-grid:has(.participant:nth-child(n+7)) .participant:nth-child(8) {
  top: 175px; /* 135px height + 40px gap */
}

.participants-grid:has(.participant:nth-child(n+7)) .participant:nth-child(9) {
  top: 330px;
}

.participants-grid:has(.participant:nth-child(n+7)) .participant:nth-child(10) {
  top: 485px;
}

.participant:hover {
  border-color: #4a9eff;
  box-shadow: 0 8px 20px rgba(74, 158, 255, 0.4);
  transform: scale(1.02);
}

.participant.local {
  border-color: #28a745;
  border-width: 3px;
  box-shadow: 0 6px 16px rgba(40, 167, 69, 0.4);
}

.participant video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}

.participant.local video {
  transform: scaleX(-1);
}

.participant-name {
  position: absolute;
  bottom: 8px;
  left: 8px;
  right: 8px;
  background: rgba(0, 0, 0, 0.85);
  color: white;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-radius: 6px;
  z-index: 10;
}

.participant.local .participant-name {
  background: rgba(40, 167, 69, 0.9);
  color: white;
}

.participant.local .participant-name::after {
  content: " (You)";
  opacity: 0.9;
  font-size: 11px;
}

/* Player portrait overlay */
.participant-portrait {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 60px;
  height: 60px;
  z-index: 5;
  pointer-events: none;
}

.participant-portrait-img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 2px solid #2991de;
  object-fit: cover;
  background: #6cace4;
}

/* Hide corner portrait when camera is off (full portrait shown instead) */
.participant.camera-off .participant-portrait {
  display: none !important;
}

/* QUE-415 — per-tile vulnerability + condition pills.
   Top-LEFT corner (portrait sits top-right, name tag sits bottom) so pills never
   cover a face. Flex-wrap so multiple pills stack cleanly within the tile width. */
.tile-pills {
  position: absolute;
  top: 6px;
  left: 6px;
  right: 72px; /* leave room for the top-right portrait so pills never overlap it */
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  z-index: 8; /* above portrait (5), below name tag (10) */
  pointer-events: none;
}

/* Compact, legible-over-video pill. The condition-* tint classes (shared with the
   character-card badges) supply colour; this only sets the compact sizing + a
   readable text shadow / blur backdrop for contrast over moving video. The
   `.tile-pills` descendant scope (specificity 0,2,0) guarantees the compact sizing
   wins over the shared `.condition-badge` base regardless of stylesheet order. */
.tile-pills .tile-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border-radius: 9px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  /* The cap-height trim lives on the label only: on the pill it shrank the
     box to capital-letter height and the emoji stuck out above and below
     (Asa, 2026-09-28). */
}

.tile-pills .tile-pill .tile-pill-icon {
  font-size: 10px;
  line-height: 1;
  height: 1em;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.tile-pills .tile-pill .tile-pill-label {
  overflow: hidden;
  text-overflow: ellipsis;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
  /* The trimmed box ends at the baseline, so overflow: hidden (needed for the
     ellipsis) cut every descender: "Limping" read "Limpina". Room for the
     descender inside the box, taken back outside it so centring is unchanged. */
  padding-bottom: 0.25em;
  margin-bottom: -0.25em;
}

/* Vulnerable pill — matches the red Vulnerable notification / status overlay. */
.tile-pills .tile-pill.tile-pill-vulnerable {
  background: rgba(220, 50, 50, 0.85);
  color: #fff;
  border: 1px solid rgba(255, 90, 90, 0.9);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

/* Video controls - Fixed at bottom of character sheet container */
.video-controls {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 400px;  /* Match character container width */
  display: none;  /* Hidden by default, shown when character sheet appears */
  justify-content: center;
  align-items: center;
  gap: 10px;
  padding: 12px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 2px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
  z-index: 100;  /* Below modals (1000) but above normal content */
}

/* Show controls when character sheet is visible */
.video-controls.show {
  display: flex !important;
}

/* Facilitator controls - centered at bottom, above QuestAI panel */
.video-container.facilitator-mode .video-controls {
  left: 50%;
  transform: translateX(-50%);
  width: auto;
  display: flex !important;  /* Always visible for facilitator */
  border-radius: 25px 25px 0 0;
  bottom: calc(5vh + 100px);  /* Position above QuestAI panel (5vh bottom + 84px height + margin) */
}

.control-btn {
  width: 48px;              /* slightly smaller */
  height: 48px;
  border-radius: 50%;
  border: 3px solid #ced4da;
  background: #ffffff;
  color: #495057;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  transition: all 0.3s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}

.control-btn .control-icon {
  width: 24px;
  height: 24px;
  filter: brightness(0) saturate(100%) invert(27%) sepia(12%) saturate(1019%) hue-rotate(177deg) brightness(95%) contrast(91%);
  transition: filter 0.3s ease;
}

.control-btn:hover .control-icon {
  filter: brightness(0) saturate(100%) invert(41%) sepia(85%) saturate(1352%) hue-rotate(204deg) brightness(103%) contrast(101%);
}

.control-btn.active .control-icon,
.control-btn.disabled .control-icon {
  filter: brightness(0) invert(1);
}

.control-btn.leave-btn .control-icon,
.control-btn.settings-btn .control-icon {
  filter: brightness(0) invert(1);
}

.control-btn:hover {
  background: #f8f9fa;
  border-color: #007bff;
  color: #007bff;
  transform: scale(1.05);
  box-shadow: 0 4px 12px rgba(0,123,255,0.2);
}

.control-btn.disabled {
  background: #f8d7da;
  border-color: #f5c6cb;
  color: #721c24;
}

.control-btn.disabled:hover {
  background: #f5c6cb;
  border-color: #f1aeb5;
  transform: scale(1.02);
}

.control-btn.active {
  background: #007bff;
  border-color: #0056b3;
  color: white;
}

.control-btn.active:hover {
  background: #0056b3;
  border-color: #004085;
}

.control-btn.leave-btn {
  background: #dc3545;
  border-color: #c82333;
  color: white;
}

.control-btn.leave-btn:hover {
  background: #c82333;
  border-color: #bd2130;
  transform: scale(1.05);
}

.control-btn.settings-btn {
  background: #6c757d;
  border-color: #5a6268;
  color: white;
}

.control-btn.settings-btn:hover {
  background: #5a6268;
  border-color: #545b62;
}

/* Device settings panel */
.device-settings {
  position: absolute;
  bottom: 90px;
  right: 20px;
  background: linear-gradient(180deg, #5BA3E5 0%, #4A8BC2 100%);
  border: 2px solid rgba(255,255,255,0.9);
  border-radius: 12px;
  padding: 20px;
  min-width: 280px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 1000;
  box-shadow: 0 8px 25px rgba(0,0,0,0.25);
}

.device-group {
  margin-bottom: 15px;
}

.device-group:last-child {
  margin-bottom: 0;
}

.device-group label {
  display: block;
  color: #ffffff;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 5px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.device-group select {
  width: 100%;
  padding: 8px 12px;
  background: rgba(255,255,255,0.9);
  border: 2px solid rgba(255,255,255,0.5);
  border-radius: 6px;
  color: #2b7ac6;
  font-size: 14px;
  outline: none;
  transition: border-color 0.3s ease;
}

.device-group select:focus {
  border-color: rgba(255,255,255,1);
  background: #ffffff;
}

.device-group select option {
  background: #ffffff;
  color: #2b7ac6;
}

/* Screen sharing controls overlay */
.screen-sharing-controls {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.95);
  border: 2px solid #e9ecef;
  border-radius: 25px;
  padding: 10px 20px;
  display: flex;
  gap: 10px;
  align-items: center;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  z-index: 1001;
}

.screen-sharing-indicator {
  color: #dc3545;
  font-weight: 600;
  font-size: 14px;
}

.stop-sharing-btn {
  background: #dc3545;
  color: white;
  border: none;
  border-radius: 15px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.stop-sharing-btn:hover {
  background: #c82333;
}

/* Responsive adjustments */
@media (max-width: 1200px) {
  .character-container {
    flex: 0 0 400px; /* stays fixed */
  }

  .screen-sharing-sidebar {
    flex: 0 0 200px;
  }
}

/* Small screen responsive adjustments (tablets) */
@media (min-width: 769px) and (max-width: 1024px) {
  .character-container {
    flex: 0 0 350px;
  }

  .control-btn {
    width: 44px;
    height: 44px;
    font-size: 18px;
  }

  /* Dice system responsive */
  .dice-and-timer-container {
    flex-direction: row;
    height: auto;
    min-height: 60px;
  }

  #dice-area {
    width: 100% !important;
    padding: 10px;
    min-height: 200px;
  }

  .dice-slot {
    width: 38px !important;
    height: 38px !important;
    font-size: 18px !important;
    border-width: 2px !important;
  }

  #dice-controls-container {
    position: static;
    width: 100%;
    margin-top: 10px;
    padding: 10px;
  }

  .roll-dice-btn {
    width: 100%;
    min-width: auto;
    font-size: 16px;
    padding: 14px 24px;
  }

  .special-actions-group {
    flex-direction: column;
    gap: 8px;
  }

  .push-luck-btn, .pay-price-btn {
    width: 100%;
    min-width: auto;
    font-size: 14px;
    padding: 10px 16px;
  }

}

/* Mobile portrait (< 576px) */
@media (max-width: 575px) {
  #dice-area {
    padding: 8px;
    gap: 6px;
  }

  .dice-slot {
    width: 32px !important;
    height: 32px !important;
    font-size: 16px !important;
    border-width: 1.5px !important;
    border-radius: 6px !important;
  }

  .roll-dice-btn {
    font-size: 15px;
    padding: 12px 20px;
  }

  .dice-status-message {
    font-size: 12px;
    padding: 8px 12px;
  }

  .soft-reset-btn {
    font-size: 16px;
    padding: 6px 10px;
  }
}

/* ========================================
   MOBILE 3-SCREEN SWIPEABLE LAYOUT
   Character > Game > Chat
   ======================================== */

@media (max-width: 768px) {
  /* Reset body for mobile */
  html {
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: 100vw !important;
    overflow: hidden !important; /* Safari fallback (doesn't support clip) */
    overflow: clip !important; /* clip prevents scroll WITHOUT clipping position:fixed elements */
  }
  body, body.video-mode {
    padding: 0 !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: 100vw !important;
    overflow: hidden !important;
  }

  body.video-mode {
    display: block !important;
    min-height: 100svh !important;
    background: transparent !important;
  }

  /* Hide listening tag on mobile */
  #listening-tag {
    display: none !important;
  }

  /* Notification center must render above 3-screen layout.
     QUE-126: clear .mobile-timer-island (offset 40px + ~40px height) + 12px gap so
     toasts don't cover the tension timer. */
  #qw-notification-center {
    top: calc(env(safe-area-inset-top, 0px) + 92px) !important;
    right: 10px !important;
    left: 10px !important;
    z-index: 10001 !important;
  }

  .game-notification {
    min-width: auto;
    max-width: none;
    font-size: 13px;
  }

  /* Show backdrop behind all screens */
  .backdrop-container {
    display: block !important;
    position: fixed !important;
    z-index: -1 !important;
  }

  /* ========================================
     PULL TAB NAVIGATION MENU
     ======================================== */
  .mobile-pull-tab {
    position: fixed;
    top: env(safe-area-inset-top, 0px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 9998;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* The box is as wide as the hidden menu (357px on a 390px phone). Only the handle and the open menu take taps,
       so the empty box no longer swallows taps meant for what sits under it (the end screen's Skip to results). */
    pointer-events: none;
  }

  .mobile-pull-tab-handle { pointer-events: auto; }

  /* The quest summary covers the game screens, so the menu has nothing to switch to while it is up. */
  body:has(> .quest-summary-overlay) .mobile-pull-tab { display: none; }

  .mobile-pull-tab-handle {
    width: 48px;
    height: 10px;
    background: rgba(255, 255, 255, 0.6);
    border-radius: 0 0 8px 8px;
    cursor: pointer;
    transition: all 0.2s ease;
    /* Expand tap target with padding */
    padding: 12px 24px;
    background-clip: content-box;
  }

  .mobile-pull-tab-handle:hover,
  .mobile-pull-tab.open .mobile-pull-tab-handle {
    background: rgba(255, 255, 255, 0.9);
    background-clip: content-box;
  }

  .mobile-nav-menu {
    display: flex;
    align-items: center;
    gap: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-radius: 0 0 16px 16px;
    padding: 12px 8px;
    margin-top: 0;
    transform: translateY(-100%);
    opacity: 0;
    transition: all 0.3s ease;
    pointer-events: none;
  }

  .mobile-pull-tab.open .mobile-nav-menu {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }

  .mobile-nav-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 12px 24px;
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.6);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
    border-radius: 8px;
  }

  .mobile-nav-btn:hover {
    background: rgba(255, 255, 255, 0.1);
  }

  .mobile-nav-btn.active {
    color: white;
    background: rgba(41, 145, 222, 0.3);
  }

  .mobile-nav-btn svg {
    width: 24px;
    height: 24px;
  }

  /* ========================================
     3-SCREEN CONTAINER
     ======================================== */
  .mobile-screen-container {
    display: flex !important;
    width: 300vw;
    height: 100svh;
    transform: translateX(-100vw); /* Start on Game screen (middle) */
    transition: transform 0.3s ease-out;
    will-change: transform;
  }

  /* Prevent accidental taps during active swipe drag */
  .mobile-screen-container.dragging * {
    pointer-events: none !important;
  }

  /* Headphones modal must remain tappable even during drag */
  .mobile-screen-container.dragging #headphones-modal,
  .mobile-screen-container.dragging #headphones-modal * {
    pointer-events: auto !important;
  }

  /* Headphones modal must sit above pull tab (z-index 9998) */
  #headphones-modal {
    z-index: 9999 !important;
    pointer-events: auto !important;
  }

  .mobile-screen-container[data-screen="character"] {
    transform: translateX(0);
  }

  .mobile-screen-container[data-screen="game"] {
    transform: translateX(-100vw);
  }

  .mobile-screen-container[data-screen="chat"] {
    transform: translateX(-200vw);
  }

  .mobile-screen {
    width: 100vw;
    height: 100svh;
    flex-shrink: 0;
    overflow: hidden;
  }

  /* Character screen needs vertical scroll — card content can exceed viewport */
  .mobile-screen[data-screen="character"] {
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }

  /* ========================================
     SCREEN 1: CHARACTER
     ======================================== */
  .mobile-screen[data-screen="character"] {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .mobile-screen[data-screen="character"] .character-container {
    display: block !important;
    position: relative !important;
    width: 100% !important;
    height: auto !important;
    min-height: 100% !important;
    max-height: none !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: visible !important;
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    flex: none !important;
    border-right: none !important;
  }

  .mobile-screen[data-screen="character"] #character-card,
  .mobile-screen[data-screen="character"] #character-card.card {
    display: block !important;
    position: relative !important;
    z-index: auto !important;
    width: 100% !important;
    min-height: 100svh !important;
    max-width: 100% !important;
    margin: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 16px !important;
    padding-top: calc(48px + env(safe-area-inset-top, 0px)) !important;
    padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)) !important;
    background: rgba(0, 0, 0, 0.35) !important;
    backdrop-filter: blur(16px) !important;
    -webkit-backdrop-filter: blur(16px) !important;
    box-sizing: border-box !important;
  }

  /* ========================================
     SCREEN 2: GAME
     ======================================== */
  .mobile-screen[data-screen="game"] {
    display: flex;
    flex-direction: column;
    position: relative;
  }

  /* Centered timer island — separate box above dice pool */
  .mobile-timer-island {
    position: absolute;
    top: calc(40px + env(safe-area-inset-top, 0px)); /* below pull tab + notch */
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 16px;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-radius: 20px;
    z-index: 11;
  }

  .mobile-timer-island .timer-compact {
    display: flex !important;
    font-size: 13px !important;
    padding: 2px 6px;
    color: rgba(255, 255, 255, 0.9);
    gap: 4px;
  }

  .mobile-timer-island .timer-compact-label {
    color: rgba(255, 255, 255, 0.6);
  }

  .mobile-timer-island .timer-compact-value {
    font-size: 13px;
    padding: 1px 6px;
    background: rgba(255, 255, 255, 0.15);
    border-radius: 4px;
    border: 1px solid rgba(255, 255, 255, 0.25);
  }

  /* Floating HUD — dice pool with portraits on top, dice below */
  .mobile-game-hud {
    position: absolute;
    top: calc(90px + env(safe-area-inset-top, 0px)); /* below timer island */
    left: 12px;
    right: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 12px;
    z-index: 10;
  }

  .mobile-game-hud #dice-area {
    flex: 1;
    display: flex !important;
    flex-direction: column;
    gap: 6px;
    padding: 0 !important;
    min-height: auto !important;
  }

  /* The mobile HUD stacks #dice-area as a COLUMN (portraits, dice, then this),
     so the button would stretch to the full width of the HUD. Hug its content
     and sit under the left edge of the pool instead. */
  .mobile-game-hud .risk-why {
    align-self: flex-start;
  }

  /* "See Why" dropdown must stay inside a phone-width HUD. The global rule
     already clamps width to the viewport and _positionRiskWhyPanel clamps the
     offset; the HUD sits 12px in from each edge, so tighten the width to match
     rather than re-anchoring it. */
  .mobile-game-hud .risk-why-panel {
    max-width: calc(100vw - 40px);
  }

  /* Portraits row on top */
  .mobile-game-hud .pool-participant-stack {
    display: flex;
    width: 100%;
    margin-right: 0;
    margin-bottom: 2px;
  }

  .mobile-game-hud .pool-participant-avatar {
    width: 28px;
    height: 28px;
    border-width: 2px;
  }

  .mobile-game-hud .pool-participant-avatar span {
    font-size: 11px;
  }

  /* Dice row below */
  .mobile-game-hud .dice-slots-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }

  .mobile-game-hud .dice-slot {
    width: 32px !important;
    height: 32px !important;
    min-width: 32px !important;
    min-height: 32px !important;
    font-size: 14px !important;
  }

  /* Timer styles moved to .mobile-timer-island above */

  /* Game video area - HIDDEN in portrait, visible only in landscape */
  .mobile-game-video-area {
    display: none !important;
  }

  /* QuestAI area — frosted glass narrative card, bottom half of screen */
  .mobile-game-questai-area {
    position: absolute;
    bottom: calc(40px + env(safe-area-inset-bottom, 0px)); /* above indicator dots + home indicator */
    left: 10px;
    right: 10px;
    top: auto;
    min-height: 80px;
    max-height: 65svh; /* taller panel — more room for narrative text */
    background: rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-radius: 16px;
    padding: 12px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Defense-in-depth: reset desktop-only inline styles on mobile even if panel
     hasn't been moved into .mobile-game-questai-area yet (observer race condition). */
  #questai-panel {
    position: relative !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    padding: 8px !important;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
  }

  .mobile-game-questai-area #questai-panel {
    display: flex !important;
    flex-direction: row !important;
    align-items: flex-start !important;
    gap: 8px !important;
    position: relative !important;
    width: 100% !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    min-height: auto !important;
    height: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }

  /* Avatar — compact circle, aligned with text */
  .mobile-game-questai-area #questai-avatar-circle {
    position: relative !important;
    width: 40px !important;
    height: 40px !important;
    min-width: 40px !important;
    left: auto !important;
    top: auto !important;
    transform: none !important;
    flex-shrink: 0 !important;
    align-self: flex-start !important;
    margin-top: 2px;
  }

  /* Scale thinking ring SVG to fit 40px mobile avatar */
  .mobile-game-questai-area #thinking-progress-ring {
    display: block !important;
    width: 46px !important;
    height: 46px !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) rotate(-90deg) !important;
  }

  /* Avatar background fits 44px */
  .mobile-game-questai-area #questai-avatar-bg,
  .mobile-game-questai-area #questai-avatar-img-wrapper {
    border-radius: 50% !important;
  }

  /* Content — fills remaining space next to avatar, flex row for text + Submit */
  .mobile-game-questai-area #questai-content {
    margin-left: 0 !important;
    flex: 1 !important;
    min-width: 0 !important;
    width: auto !important;
    display: flex !important;
    flex-direction: row !important; /* override desktop column — 3-col: avatar | text | submit */
    align-items: center !important;
    gap: 8px !important;
  }

  /* Submit button: flex item instead of absolute overlay */
  .mobile-game-questai-area #manual-send-btn {
    position: static !important;
    right: auto !important;
    top: auto !important;
    transform: none !important;
    flex-shrink: 0 !important;
  }

  /* QuestAI response text — light color for dark glass background */
  .mobile-game-questai-area #questai-response-compact {
    max-height: none !important;
    overflow: visible !important;
    -webkit-line-clamp: unset !important;
    color: rgba(255, 255, 255, 0.95) !important;
    font-size: 1em !important;
    line-height: 1.5 !important;
    word-break: break-word !important;
    flex: 1 !important;
    min-width: 0 !important;
  }

  .mobile-game-questai-area #questai-response-compact strong {
    color: #6fd5ff !important;
  }

  .mobile-game-questai-area #questai-response-compact em {
    color: rgba(255, 255, 255, 0.85) !important;
  }

  /* Status display — match dark theme */
  .mobile-game-questai-area #quest-status-display {
    color: rgba(255, 255, 255, 0.5) !important;
  }

  /* Hide desktop controls (buttons) on mobile */
  .mobile-game-questai-area #questai-controls {
    display: none !important;
  }

  /* CRITICAL: Hide QuestAI panel on non-Game screens */
  body.video-mode #questai-panel {
    display: none !important;
  }

  /* Only show QuestAI in the game screen's designated area.
     Must beat body.video-mode #questai-panel { display: none } specificity (1,1,1) */
  body.video-mode .mobile-game-questai-area #questai-panel {
    display: flex !important;
  }

  /* ========================================
     PULL-TAB: VIDEO/AUDIO CONTROLS
     ======================================== */
  .mobile-nav-divider {
    width: 1px;
    height: 32px;
    background: rgba(255, 255, 255, 0.2);
    margin: 0 4px;
    align-self: center;
  }

  .mobile-nav-control-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: rgba(255, 255, 255, 0.1);
    border: none;
    border-radius: 50%;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 0;
  }

  .mobile-nav-control-btn:hover,
  .mobile-nav-control-btn:active {
    background: rgba(255, 255, 255, 0.2);
  }

  .mobile-nav-control-btn .control-icon {
    filter: brightness(0) invert(1);
    opacity: 0.8;
  }

  .mobile-nav-control-btn[aria-pressed="false"] {
    background: rgba(220, 53, 69, 0.5);
  }

  .mobile-nav-control-btn[aria-pressed="false"] .control-icon {
    opacity: 0.5;
  }

  /* Device settings dialog on mobile */
  .mobile-device-settings {
    position: fixed;
    top: 80px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10000;
    background: rgba(0, 0, 0, 0.9);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 16px;
    padding: 16px;
    width: 90vw;
    max-width: 360px;
  }

  /* Landscape rules are OUTSIDE this media query — see below */

  /* ========================================
     SCREEN 3: CHAT
     ======================================== */
  .mobile-screen[data-screen="chat"] #transcript-sidebar {
    position: relative !important;
    transform: none !important;
    width: 100% !important;
    height: 100svh !important;
    right: auto !important;
    display: flex !important;
    flex-direction: column !important;
    background: rgba(0, 0, 0, 0.35) !important;
    backdrop-filter: blur(20px) !important;
    -webkit-backdrop-filter: blur(20px) !important;
  }

  .mobile-screen[data-screen="chat"] .transcript-header {
    padding: 12px 16px !important;
    padding-top: calc(48px + env(safe-area-inset-top, 0px)) !important; /* Pull tab + notch */
    border-bottom: 1px solid rgba(255, 255, 255, 0.2) !important;
  }

  .mobile-screen[data-screen="chat"] .transcript-header h2 {
    font-size: 18px !important;
    font-weight: 600 !important;
  }

  /* Hide the close button on chat screen (use navigation instead) */
  .mobile-screen[data-screen="chat"] .transcript-close-btn {
    display: none !important;
  }

  /* Content area — tighter padding */
  .mobile-screen[data-screen="chat"] .transcript-content {
    padding: 12px 14px !important;
  }

  /* Messages — smaller font and spacing */
  .mobile-screen[data-screen="chat"] .transcript-message {
    font-size: 13px !important;
    padding: 10px 0 !important;
    line-height: 1.5 !important;
  }

  /* Chat input — compact, respects home indicator */
  .mobile-screen[data-screen="chat"] .chat-input-container {
    padding: 10px 12px !important;
    padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px)) !important;
  }

  .mobile-screen[data-screen="chat"] .chat-input {
    padding: 10px 14px !important;
    font-size: 16px !important; /* must be >= 16px to prevent iOS auto-zoom on focus */
  }

  .mobile-screen[data-screen="chat"] .chat-send-btn {
    width: 40px !important;
    height: 40px !important;
  }

  /* ========================================
     SWIPE TUTORIAL OVERLAY
     ======================================== */
  .swipe-tutorial-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.9);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 99999;
    padding: 24px;
    text-align: center;
  }

  .mobile-beta-banner {
    padding: 10px 16px;
    margin-bottom: 20px;
    background: rgba(255, 180, 0, 0.15);
    border: 1.5px solid rgba(255, 180, 0, 0.45);
    border-radius: 10px;
    color: #fff;
    font-size: 13px;
    line-height: 1.5;
    max-width: 340px;
    text-align: center;
  }

  .mobile-beta-banner strong {
    color: #ffd966;
  }

  .swipe-tutorial-screens {
    display: flex;
    gap: 24px;
    margin-bottom: 32px;
  }

  .swipe-tutorial-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 16px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    color: rgba(255, 255, 255, 0.6);
    font-size: 12px;
    font-weight: 600;
  }

  .swipe-tutorial-screen.active {
    background: rgba(41, 145, 222, 0.3);
    color: white;
  }

  .swipe-tutorial-screen svg {
    width: 32px;
    height: 32px;
  }

  .swipe-tutorial-hand {
    font-size: 48px;
    animation: swipeHintAnim 1.5s ease-in-out infinite;
    margin-bottom: 16px;
  }

  @keyframes swipeHintAnim {
    0%, 100% { transform: translateX(-40px); }
    50% { transform: translateX(40px); }
  }

  .swipe-tutorial-text {
    color: white;
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 8px;
  }

  .swipe-tutorial-subtext {
    color: rgba(255, 255, 255, 0.6);
    font-size: 14px;
    margin-bottom: 24px;
  }

  .swipe-tutorial-btn {
    padding: 14px 32px;
    background: #2991de;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
    margin-top: 16px;
  }

  /* 2-step tutorial system */
  .tutorial-step {
    display: none;
    flex-direction: column;
    align-items: center;
  }

  .tutorial-step-active {
    display: flex;
  }

  .tutorial-rotate-icon {
    margin-bottom: 24px;
    animation: tutorialRotateHint 2s ease-in-out infinite;
  }

  @keyframes tutorialRotateHint {
    0%, 100% { transform: rotate(0deg); }
    25% { transform: rotate(15deg); }
    75% { transform: rotate(-15deg); }
  }

  .tutorial-step-dots {
    display: flex;
    gap: 8px;
    margin-top: 24px;
  }

  .tutorial-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
    cursor: pointer;
    transition: all 0.2s ease;
  }

  .tutorial-dot.active {
    background: white;
    width: 20px;
    border-radius: 4px;
  }

  /* ========================================
     SCREEN INDICATOR DOTS
     ======================================== */
  .mobile-screen-indicator {
    position: fixed;
    bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 8px;
    z-index: 100;
    padding: 8px 16px;
    background: rgba(0, 0, 0, 0.4);
    border-radius: 16px;
  }

  .mobile-screen-indicator .dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
    transition: all 0.2s ease;
    cursor: pointer;
    position: relative;
  }

  /* Expanded tap target for dots */
  .mobile-screen-indicator .dot::before {
    content: '';
    position: absolute;
    top: -17px;
    left: -17px;
    right: -17px;
    bottom: -17px;
  }

  .mobile-screen-indicator .dot.active {
    background: white;
    width: 24px;
    border-radius: 5px;
  }

  /* === Small Screen Optimizations === */

  /* Reduce QuestAI max-height on short phones (iPhone SE, 12 mini) */
  @media (max-height: 700px) {
    .mobile-game-questai-area {
      max-height: 45svh !important;
    }
  }

  /* Tighter section spacing on character sheet */
  .mobile-screen[data-screen="character"] .section {
    margin-bottom: 18px !important;
  }
  .mobile-screen[data-screen="character"] .section:last-child {
    margin-bottom: 0 !important;
  }

  /* Icon-only nav buttons on narrow screens */
  @media (max-width: 400px) {
    .mobile-nav-btn {
      padding: 12px 14px !important;
    }
    .mobile-nav-btn span {
      display: none !important;
    }
  }

  /* Tighter QuestAI padding on narrow screens */
  @media (max-width: 390px) {
    .mobile-game-questai-area {
      padding: 12px !important;
    }
  }
}

/* Tablet (576px - 991px) */
@media (min-width: 576px) and (max-width: 991px) {
  #dice-area {
    width: 70% !important;
    padding: 12px;
  }

  .dice-slot {
    width: 40px !important;
    height: 40px !important;
    font-size: 20px !important;
  }

  #dice-controls-container {
    right: 8px;
    bottom: 8px;
  }

  .roll-dice-btn {
    min-width: 180px;
  }

}

/* ========================================
   MOBILE LANDSCAPE VIDEO FEED
   Outside @media(max-width:768px) because landscape viewport width
   exceeds 768px on most phones, which would disable the overlay.
   These classes are only created by JS on mobile, so no desktop impact.
   ======================================== */
.mobile-landscape-video {
  display: none;
  position: fixed;
  inset: 0;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  /* JS sets background to: linear-gradient(dark overlay), url(backdrop) center/cover */
  /* Fallback when no backdrop image is available */
  background: rgba(0, 0, 0, 0.7);
  z-index: 9999;
}

.mobile-landscape-video.active {
  display: flex;
  flex-direction: column;
  height: 100dvh;
}

/* Hide listening tag when landscape overlay is active (it leaks through
   because landscape viewport > 768px, so the portrait @media rule doesn't apply) */
.mobile-landscape-video.active ~ * #listening-tag,
body:has(.mobile-landscape-video.active) #listening-tag {
  display: none !important;
}

/* Bottom control bar — frosted glass, not solid black */
.landscape-controls {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 8px 16px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
  background: rgba(0, 0, 0, 0.25);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  flex-shrink: 0;
  width: 100%;
  order: 1;
}

/* Video area */
.landscape-video-grid {
  flex: 1;
  min-width: 0;
  min-height: 0;
  padding: 8px;
  padding-left: calc(8px + env(safe-area-inset-left));
  padding-right: calc(8px + env(safe-area-inset-right));
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  display: flex;
  align-items: stretch;
}

.landscape-video-grid .participants-grid {
  position: relative !important;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  bottom: auto !important;
  width: auto !important;
  min-width: min-content !important;
  height: 100% !important;
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap !important;
  gap: 6px !important;
  pointer-events: auto !important;
}

.landscape-video-grid .participant {
  position: relative !important;
  width: auto !important;
  min-width: 160px !important;
  height: 100% !important;
  aspect-ratio: 16 / 9;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  bottom: auto !important;
  transform: none !important;
  flex-shrink: 0 !important;
  border-radius: 10px;
  overflow: hidden;
}

.landscape-video-grid .participant video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
}

.landscape-control-btn {
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s ease;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.landscape-control-btn:active {
  background: rgba(255, 255, 255, 0.3);
}

.landscape-control-btn .control-icon {
  filter: brightness(0) invert(1);
}

/* Off state — red tint + dimmed icon (synced from main button .disabled class) */
.landscape-control-btn.disabled {
  background: rgba(220, 53, 69, 0.5);
}

.landscape-control-btn.disabled .control-icon {
  opacity: 0.5;
}

.landscape-rotate-hint {
  display: none;
}

/* Loading state */
.participant.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #6c757d;
  font-size: 14px;
  background: #f8f9fa;
}

.participant.loading::before {
  content: "";
  width: 30px;
  height: 30px;
  border: 3px solid #e9ecef;
  border-top: 3px solid #007bff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-right: 10px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* Error states */
.participant.error {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #721c24;
  font-size: 12px;
  text-align: center;
  padding: 10px;
  background: #f8d7da;
}

/* Accessibility improvements */
.control-btn:focus {
  outline: 3px solid rgba(0, 123, 255, 0.4);
  outline-offset: 2px;
}

/* Animation for layout changes */
.participants-grid,
.participant {
  transition: all 0.3s ease;
}

/* When screen sharing is active, hide main participants grid */
.video-container.screen-sharing-mode:not(.facilitator-screen-sharing) .participants-grid {
  display: none;
}

/* When facilitator is screen sharing, overlay the participants grid */
.video-container.facilitator-screen-sharing .participants-grid {
  position: absolute;
  top: 20px;
  bottom: 100px;
  right: 20px;
  width: 280px;
  height: auto;
  padding: 0;
  margin-bottom: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 10px;
  align-content: flex-start;
  justify-content: flex-start;
  z-index: 100;
}

.video-container.facilitator-screen-sharing .participant {
  flex: 0 0 auto;
  width: 100%;
  max-width: 100%;
  aspect-ratio: 16/9;
  background: #111;
  border: 2px solid rgba(255,255,255,0.3);
  box-shadow: 0 4px 12px rgba(0,0,0,0.5);
}

/* Screen share label overlay */
.screen-sharer-label {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,0.2);
}

/* Centered portrait fallback (shown when participant camera is off) */
.participant-centered-portrait {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end; /* Bottom-align the large portrait so it sprouts from the name label */
  z-index: 6;
  pointer-events: none;
  background: #6cace4 !important; /* Solid blue, fills the entire tile */
  margin: 0 !important;
  /* Reserve space at top and bottom (for rounded corners/name bar) + small side padding */
  padding: 32px 4% 64px; /* allow JS to override padding dynamically for exact label height */
  border: none !important;
  box-shadow: none !important;
  overflow: hidden;
  box-sizing: border-box;
}

.participant-centered-inner {
  width: 100%;
  height: 100%;
  max-width: 900px;
  max-height: 100%;
  display: flex;
  align-items: flex-end; /* bottom-align image within overlay */
  justify-content: center;
  border-radius: 12px;
  background: transparent;
  box-shadow: none;
  overflow: hidden;
  border: none;
  margin: 0;
}

.participant-centered-img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain; /* Show full portrait without cropping */
  border-radius: 8px;
  display: block;
}

.participant-centered-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 48px;
  font-weight: 800;
  letter-spacing: 2px;
  user-select: none;
}

/* Slightly dim underlying video while portrait fallback is visible */
.participant .participant-centered-portrait ~ video {
  filter: brightness(0.35) saturate(0.9);
}

/* Ensure portrait border for the small corner avatar uses the requested color (already present, kept for clarity) */
.participant-portrait-img {
  background: #6cace4;
}

/* ========================================================================
   DICE CONTROL BUTTONS (Bottom-Right Fixed Position)
   ======================================================================== */

.dice-controls-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  z-index: 100;
  pointer-events: auto;
}

/* Roll Dice Button */
.roll-dice-btn {
  background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  color: white;
  border: 3px solid rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  padding: 16px 32px;
  font-size: 18px;
  font-weight: 700;
  font-family: 'League Spartan', sans-serif;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  text-transform: uppercase;
  letter-spacing: 1px;
  min-width: 200px;
  text-align: center;
}

.roll-dice-btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.5);
  background: linear-gradient(135deg, #20c997 0%, #28a745 100%);
}

.roll-dice-btn:active:not(:disabled) {
  transform: translateY(0);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}

.roll-dice-btn:disabled {
  background: rgba(150, 150, 150, 0.5);
  cursor: default !important; /* AI controls rolling now */
  opacity: 0.7;
  border-color: rgba(255, 255, 255, 0.4);
  pointer-events: none; /* Disable all interactions */
}

.roll-dice-btn.rolling {
  background: linear-gradient(135deg, #ffc107 0%, #ff9800 100%);
  animation: pulse 1s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

/* AI Suggested Roll Animation */
.roll-dice-btn.ai-suggested {
  animation: aiSuggestPulse 1.5s ease-in-out 2;
  box-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 8px 25px rgba(0, 0, 0, 0.5);
}

@keyframes aiSuggestPulse {
  0%, 100% {
    transform: scale(1);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  }
  50% {
    transform: scale(1.08);
    box-shadow: 0 0 25px rgba(255, 215, 0, 0.9), 0 10px 30px rgba(0, 0, 0, 0.6);
  }
}

/* Screen reader only (accessible but invisible) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* Status Message */
.dice-status-message {
  background: rgba(41, 145, 222, 0.9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: white;
  padding: 10px 16px;
  border-radius: 8px;
  border: 2px solid rgba(255, 255, 255, 0.6);
  font-size: 13px;
  font-weight: 600;
  max-width: 280px;
  text-align: center;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
  line-height: 1.3;
}

/* Special Actions Container */
.special-actions-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
}

.special-action-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Special Action Buttons */
.special-action-btn {
  background: linear-gradient(135deg, #6f42c1 0%, #9c36b5 100%);
  color: white;
  border: 3px solid rgba(255, 255, 255, 0.9);
  border-radius: 10px;
  padding: 12px 24px;
  font-size: 16px;
  font-weight: 700;
  font-family: 'League Spartan', sans-serif;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

.special-action-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
}

.special-action-btn:active {
  transform: none;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
}

.special-action-btn.push-luck {
  background: linear-gradient(135deg, #ff6b35 0%, #f7931e 100%);
}

.special-action-btn.pay-price {
  background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
}

/* Special Action Timer */
.special-action-timer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to right, rgba(0, 0, 0, 0.7) 0%, transparent 100%);
  border-radius: 10px;
  pointer-events: none;
  transition: width 0.1s linear;
  z-index: 1;
}

/* Soft Reset Button */
.soft-reset-btn {
  background: rgba(255, 255, 255, 0.2);
  color: white;
  border: 2px solid rgba(255, 255, 255, 0.6);
  border-radius: 50%;
  width: 50px;
  height: 50px;
  font-size: 24px;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.soft-reset-btn:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: rotate(90deg) scale(1.1);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
}

.soft-reset-btn:active {
  transform: rotate(90deg) scale(1);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

/* Game Notifications */
/* Notification Center Container */
/* QUE-126: top offset clears the .dice-and-timer-container top bar (max-height 100px) + 12px gap
   so toasts never overlap the tension timer during gameplay.
   QUE-154 (revised): the objectives chip strip now renders BELOW the bar (not
   inside it), so the bar stays its original 10vh / max 100px height. The
   baseline offset is back to QUE-126's 112px. When `.has-objectives` is set
   the chip strip occupies an additional ~40px directly under the bar — see
   the `:has()` override further down for that case. */
#qw-notification-center {
  position: fixed;
  top: calc(clamp(60px, 10vh, 100px) + 20px); /* flush with top of first video tile (grid-top + 20px tile inset) */
  right: 20px;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  /* gap removed — each .game-notification owns its own margin-bottom so it can
     animate the gap to 0 during dismissal (lets survivors slide up smoothly). */
  pointer-events: none;
  max-height: calc(100vh - clamp(60px, 10vh, 100px) - 40px);
  overflow-y: hidden;
  transition: top 0.25s ease, max-height 0.25s ease;
}

.game-notification {
  position: relative;
  min-width: 300px;
  max-width: 400px;
  padding: 16px 20px;
  margin-bottom: 10px;                   /* owns its own stack gap so it can collapse on dismiss */
  max-height: 600px;                     /* cap so max-height can transition to 0 on dismiss */
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  color: white;
  font-family: 'League Spartan', sans-serif;
  font-size: 14px;
  animation: slideInRight 0.3s ease-out;
  pointer-events: auto;
  overflow: hidden;
  align-self: flex-end;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.15);
  /* On dismiss, animate every property that collapses the slot so survivors
     slide up rather than jumping. transform/opacity = the visible slide+fade;
     max-height/margin/padding/border = collapse the layout slot. */
  transition: transform 0.35s ease-in,
              opacity 0.35s ease-in,
              max-height 0.35s ease-in,
              margin 0.35s ease-in,
              padding 0.35s ease-in,
              border-width 0.35s ease-in;
}

.game-notification.notification-leaving {
  transform: translateX(400px);
  opacity: 0;
  max-height: 0;
  margin-top: 0;
  margin-bottom: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-top-width: 0;
  border-bottom-width: 0;
  pointer-events: none;
}

/* Dismiss X button */
.notification-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.5);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  pointer-events: auto;
  transition: color 0.15s;
}

.notification-close:hover {
  color: rgba(255, 255, 255, 0.9);
}

@keyframes slideInRight {
  from {
    transform: translateX(400px);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

@keyframes slideOutRight {
  from { transform: translateX(0); opacity: 1; }
  to { transform: translateX(400px); opacity: 0; }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* XP Award Notification (Blue) */
.game-notification.xp-award {
  background: rgba(33, 150, 243, 0.55);
  border-left: 4px solid rgba(100, 181, 246, 0.85);
}

/* Generic one-line notification (Green) — objective XP and other
   messages routed through NotificationManager.showNotification */
.game-notification.generic {
  background: rgba(76, 175, 80, 0.55);
  border-left: 4px solid rgba(129, 199, 132, 0.85);
}
.game-notification.generic .notification-icon {
  font-size: 14px;
  margin-right: 6px;
}

/* Risk Set Notification (Purple) */
.game-notification.risk-set {
  background: rgba(156, 39, 176, 0.55);
  border-left: 4px solid rgba(186, 104, 200, 0.85);
}

/* Notification Header */
.notification-header {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.notification-icon {
  font-size: 20px;
}

/* Notification Body */
.notification-body {
  font-size: 13px;
  line-height: 1.4;
  opacity: 0.95;
}

/* XP Breakdown */
.xp-breakdown {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
}

.xp-player-line {
  display: flex;
  justify-content: space-between;
  margin: 4px 0;
  font-size: 15px;
}

.xp-player-name {
  font-weight: 600;
}

.xp-player-amount {
  font-weight: 700;
  color: #FFD700;
}

.xp-bonus-details {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin: 6px 0 10px 0;
}

.xp-bonus-tag {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  padding: 4px 10px;
  background: rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  color: rgba(255, 255, 255, 0.85);
}

.xp-total {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.4);
  font-weight: 700;
  text-align: right;
  font-size: 18px;
}

/* Timer Adjustment Notification (standalone, queued after dice roll) */
.timer-adjustment-notice {
  min-width: 180px;
}
.timer-adjustment-body {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 8px;
  font-weight: 600;
}
.timer-adjustment-body.timer-gain {
  background: rgba(76, 175, 80, 0.25);
  color: #a5d6a7;
}
.timer-adjustment-body.timer-loss {
  background: rgba(244, 67, 54, 0.25);
  color: #ef9a9a;
}
.timer-adjustment-icon {
  font-size: 18px;
}
.timer-adjustment-value {
  font-size: 16px;
  font-weight: 700;
}
.timer-adjustment-label {
  font-size: 12px;
  opacity: 0.8;
  margin-left: auto;
}

/* Instant Result Badge (shown at top of XP notification on natural 1 or 6) */
.instant-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 700;
  color: white;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
}

.instant-fail {
  background-color: #dc3545;
}

.instant-success {
  background-color: #28a745;
}

.close-call {
  background-color: #ffc107;  /* Yellow - matches dice result 4-5 */
  color: #000;  /* Dark text for contrast on yellow */
}

.silver-lining {
  background-color: #ff9800;  /* Orange - matches dice result 2-3 */
  color: #000;  /* Dark text for contrast on orange */
}

/* Risk Adjustment Notification (Teal) */
.game-notification.risk-adjust {
  background: rgba(0, 137, 123, 0.55);
  border-left: 4px solid rgba(77, 182, 172, 0.85);
}

.risk-adjust-moves {
  margin-bottom: 8px;
}

.risk-adjust-move-line {
  font-size: 12px;
  margin: 3px 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.risk-reduction {
  font-weight: 700;
  color: #A5D6A7;
  margin-left: 8px;
}

.risk-adjust-display {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  font-weight: 700;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.3);
}

.risk-from.risk-strikethrough {
  text-decoration: line-through;
  opacity: 0.6;
}

.risk-arrow {
  font-size: 14px;
  opacity: 0.7;
}

.risk-to {
  color: #A5D6A7;
}

/* Threat Defeated Notification (Green) */
.game-notification.threat-defeated {
  background: rgba(30, 120, 60, 0.55);
  border-left: 4px solid rgba(76, 175, 80, 0.85);
}

.threat-defeated-portraits {
  display: flex;
  gap: 8px;
  margin: 8px 0;
  align-items: center;
}

.threat-defeated-portrait {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(76, 175, 80, 0.6);
  box-shadow: 0 0 10px rgba(76, 175, 80, 0.3);
}

.threat-defeated-portrait-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.4);
  color: #4CAF50;
  font-size: 18px;
}

.threat-defeated-names {
  font-size: 13px;
  color: #81C784;
  font-weight: 600;
  margin-top: 2px;
}

/* Threat Escaped Notification (Silver/Grey) */
.game-notification.threat-escaped {
  background: rgba(120, 130, 150, 0.55);
  border-left: 4px solid rgba(180, 190, 210, 0.85);
}

.game-notification.threat-escaped .threat-defeated-names {
  color: #B4BED2;
}

.game-notification.threat-escaped .threat-defeated-portrait {
  border-color: rgba(180, 190, 210, 0.6);
  box-shadow: 0 0 10px rgba(150, 160, 180, 0.3);
}

/* Vulnerable Notification (Red) */
.game-notification.vulnerable {
  background: rgba(220, 50, 50, 0.55);
  border-left: 4px solid rgba(255, 80, 80, 0.85);
}

.vulnerable-content {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.vulnerable-portrait {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 80, 80, 0.6);
  box-shadow: 0 0 10px rgba(255, 50, 50, 0.3);
  flex-shrink: 0;
}

.vulnerable-text {
  font-size: 13px;
  line-height: 1.4;
}

/* Condition Applied Notification (QUE-415) — themed by polarity so a positive
   boon reads instantly distinct from a negative. Mirrors the Vulnerable layout. */
.game-notification.condition-applied {
  background: rgba(70, 80, 100, 0.6);
  border-left: 4px solid rgba(150, 165, 195, 0.85);
}

/* Negative conditions — cool/slate (the per-element badge tint lives on the
   character card; the toast keeps a single readable negative treatment). */
.game-notification.condition-applied.condition-negative {
  background: rgba(60, 72, 92, 0.62);
  border-left: 4px solid rgba(140, 158, 190, 0.85);
}

/* Positive boons — warm/gold glow, matching the character-card boon badge. */
.game-notification.condition-applied.condition-positive {
  background: rgba(150, 110, 25, 0.6);
  border-left: 4px solid rgba(255, 205, 90, 0.9);
}

.condition-applied-content {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.condition-applied-portrait {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.4);
  flex-shrink: 0;
}

.game-notification.condition-applied.condition-positive .condition-applied-portrait {
  border-color: rgba(255, 205, 90, 0.7);
  box-shadow: 0 0 12px rgba(255, 205, 90, 0.35);
}

.condition-applied-text {
  font-size: 13px;
  line-height: 1.4;
}

/* Expertise Nudge Notification (Teal); the QUE-992 bonus objective toast shares it */
.game-notification.expertise-nudge,
.game-notification.bonus-objective {
  background: rgba(0, 150, 136, 0.55);
  border-left: 4px solid rgba(77, 208, 195, 0.85);
}

.game-notification.group-roll-coaching {
  background: rgba(255, 179, 0, 0.55);
  border-left: 4px solid #ffb300;
}

/* QUE-153 — Failure Consequence Notifications (visible to whole table) */

/* Shared portrait + text layout for consequence toasts */
.consequence-content {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.consequence-portrait {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(255, 255, 255, 0.4);
  flex-shrink: 0;
}

.consequence-text {
  font-size: 13px;
  line-height: 1.4;
}

/* Sacrifice / paid-the-price (deep crimson) — load-bearing emotional moment */
.game-notification.sacrifice-paid {
  background: rgba(150, 25, 55, 0.65);
  border-left: 4px solid rgba(240, 90, 130, 0.9);
}

.game-notification.sacrifice-paid .consequence-portrait {
  border-color: rgba(240, 90, 130, 0.7);
  box-shadow: 0 0 12px rgba(240, 90, 130, 0.35);
}

/* Push-luck (gold/amber) — the gambit moment */
.game-notification.push-luck {
  background: rgba(180, 130, 25, 0.6);
  border-left: 4px solid rgba(255, 200, 80, 0.9);
}

.game-notification.push-luck .consequence-portrait {
  border-color: rgba(255, 200, 80, 0.7);
  box-shadow: 0 0 12px rgba(255, 200, 80, 0.35);
}

/* Gear-lost (rust/orange) — your loadout just shifted */
.game-notification.gear-lost {
  background: rgba(170, 70, 30, 0.6);
  border-left: 4px solid rgba(255, 130, 70, 0.9);
}

.game-notification.gear-lost.gear-lost-own {
  background: rgba(200, 60, 30, 0.7);
  border-left: 4px solid rgba(255, 100, 60, 0.95);
}

.game-notification.gear-lost .consequence-portrait {
  border-color: rgba(255, 130, 70, 0.7);
  box-shadow: 0 0 10px rgba(255, 130, 70, 0.3);
}

/* Mechanical Q→Q display for gear quality changes (QUE-153).
   Mirrors .risk-adjust-display — game-y, not narrative. */
.gear-quality-owner {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: rgba(255, 255, 255, 0.98);
  margin-bottom: 2px;
}

.gear-quality-owner-tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.95);
}

.gear-quality-display {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.gear-quality-item {
  font-size: 13px;
  font-weight: 600;
  opacity: 0.95;
  letter-spacing: 0.2px;
  margin-right: 2px;
}

.gear-quality-from {
  color: rgba(255, 255, 255, 0.7);
  text-decoration: line-through;
  text-decoration-color: rgba(255, 255, 255, 0.4);
}

.gear-quality-arrow {
  font-size: 12px;
  opacity: 0.7;
}

.gear-quality-to {
  color: #FFB58A;
}

.gear-quality-destroyed {
  color: #FF6B4A;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-size: 13px;
}

/* Sacrifice line folded into a merged "paid a price" gear card */
.gear-sacrifice-line {
  font-size: 13px;
  font-weight: 600;
  opacity: 0.95;
  margin-top: 2px;
}

/* Legacy Expertise Instinct Nudge (bottom-right, kept for backward compat) */
/* Expertise Instinct Nudge */
.qw-expertise-nudge {
  position: fixed;
  right: 20px;
  bottom: 20px;
  max-width: 360px;
  width: calc(100vw - 40px);
  background: rgba(41, 145, 222, 0.65);
  color: #fff;
  border-radius: 14px;
  padding: 14px 14px 12px;
  box-shadow: 0 18px 38px rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  z-index: 800;
  font-family: 'League Spartan', system-ui, -apple-system, sans-serif;
  border: 1px solid rgba(255, 255, 255, 0.25);
  animation: slideInRight 0.3s ease-out, fadeOut 0.5s ease-in 9s forwards;
}

.qw-expertise-nudge-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  opacity: 0.6;
  margin-bottom: 6px;
}

.qw-expertise-nudge-body {
  font-size: 14px;
  line-height: 1.5;
  opacity: 0.95;
}

.qw-expertise-nudge-dismiss {
  display: block;
  margin-top: 10px;
  padding: 6px 16px;
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 8px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s;
}

.qw-expertise-nudge-dismiss:hover {
  background: rgba(255, 255, 255, 0.35);
}

@media (max-width: 480px) {
  .qw-expertise-nudge {
    right: 10px;
    left: 10px;
    bottom: 12px;
  }
}

/* Multiple notifications now stack via #qw-notification-center flex layout */

/* Mobile responsive notifications */
@media (max-width: 575px) {
  #qw-notification-center {
    top: 10px;
    right: 10px;
    left: 10px;
  }

  .game-notification {
    min-width: auto;
    max-width: none;
    font-size: 13px;
  }

  .notification-header {
    font-size: 15px;
  }
}


/* ════════════════════════════════════════════════════════════
   QUEST SUMMARY SCREEN — Post-quest animated overlay
   ════════════════════════════════════════════════════════════ */

.quest-summary-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(41, 145, 222, 0.65);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  padding: env(safe-area-inset-top, 20px) env(safe-area-inset-right, 20px)
           env(safe-area-inset-bottom, 20px) env(safe-area-inset-left, 20px);
  opacity: 0;
  animation: qsFadeIn 0.4s ease-out forwards;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.quest-summary-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  max-width: 900px;
  width: 100%;
  padding: 20px;
}

/* Outcome Banner */
.quest-outcome-banner {
  font-family: 'League Spartan', sans-serif;
  font-size: clamp(28px, 5vw, 56px);
  font-weight: 700;
  letter-spacing: 4px;
  text-align: center;
  text-transform: uppercase;
  padding: 12px 24px;
  transform: translateY(-60px);
  opacity: 0;
  animation: qsBannerSlideDown 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.4s forwards;
}

.quest-outcome--completed {
  color: #ffffff;
  text-shadow: 0 0 20px rgba(255, 255, 255, 0.6), 0 2px 8px rgba(0, 0, 0, 0.3);
}

.quest-outcome--failed {
  color: #ff6b6b;
  text-shadow: 0 0 20px rgba(255, 107, 107, 0.6), 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* Time ran out mid-action: neither a win nor a loss. */
.quest-outcome--incomplete {
  color: #ffd166;
  text-shadow: 0 0 20px rgba(255, 209, 102, 0.6), 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* Player Cards Container */
.quest-player-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: center;
  width: 100%;
}

/* Player Card */
.qps-card {
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 16px;
  padding: 24px 20px;
  width: 220px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  position: relative;
  transform: translateY(40px);
  opacity: 0;
  animation: qsCardIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  /* animation-delay set inline by JS */
}

.qps-card.is-mvp.is-mvp-revealed {
  border-color: rgba(255, 215, 0, 0.7);
  box-shadow: 0 0 30px rgba(255, 215, 0, 0.3), inset 0 0 20px rgba(255, 215, 0, 0.05);
  animation: qsMvpGlow 2s ease-in-out infinite;
}

/* Portrait */
.qps-portrait-wrap {
  position: relative;
  width: 80px;
  height: 80px;
  flex-shrink: 0;
}

.qps-portrait {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid rgba(255, 255, 255, 0.35);
  background: rgba(0, 0, 0, 0.2);
}

.qps-card.is-mvp.is-mvp-revealed .qps-portrait {
  border-color: #ffd700;
  box-shadow: 0 0 16px rgba(255, 215, 0, 0.5);
}

/* MVP Badge */
.qps-mvp-badge {
  display: none;
  position: absolute;
  bottom: -6px;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(135deg, #ffd700, #ffaa00);
  color: #1a1a2e;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.5px;
  padding: 3px 10px;
  border-radius: 10px;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(255, 215, 0, 0.4);
}

.qps-card.is-mvp.is-mvp-revealed .qps-mvp-badge {
  display: block;
  animation: qsScalePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

/* Info Section */
.qps-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
}

.qps-name {
  font-family: 'League Spartan', sans-serif;
  font-size: 16px;
  font-weight: 600;
  color: #ffffff;
  text-align: center;
  letter-spacing: 0.5px;
}

/* XP Line */
.qps-xp-line {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.qps-stat-icon {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.5);
}

.qps-xp-counter {
  font-size: 26px;
  font-weight: 700;
  color: #ffd700;
  font-family: 'League Spartan', sans-serif;
}

/* XP Progress Bar */
.qps-xp-bar-wrap {
  width: 100%;
  height: 6px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 3px;
  overflow: hidden;
}

.qps-xp-bar {
  height: 100%;
  background: linear-gradient(90deg, #4a9eff, #7bb3ff);
  border-radius: 3px;
  width: 0%;
  transition: width 0.8s ease-out;
}

/* Level Badge */
.qps-level-badge {
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.5px;
}

.qps-level-badge.qps-level-changed {
  color: #ffd700;
  animation: qsScalePop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Loot Tier */
.qps-loot-tier {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-align: center;
  padding: 4px 10px;
  border-radius: 8px;
  white-space: nowrap;
}

.qps-loot--rare {
  color: #ffd700;
  background: rgba(255, 215, 0, 0.12);
  border: 1px solid rgba(255, 215, 0, 0.3);
  text-shadow: 0 0 8px rgba(255, 215, 0, 0.4);
}

.qps-loot--uncommon {
  color: #4ae54a;
  background: rgba(74, 229, 74, 0.1);
  border: 1px solid rgba(74, 229, 74, 0.25);
}

.qps-loot--common {
  color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
}

/* Epic and Legendary take the tier colors QuestDash uses for gear (violet #7c3aed, amber #d97706),
   lightened for white-on-blue-glass contrast. */
.qps-loot--epic {
  color: #f3e8ff;
  background: rgba(124, 58, 237, 0.45);
  border: 1px solid rgba(196, 160, 255, 0.75);
}

.qps-loot--legendary {
  color: #fff4e0;
  background: rgba(217, 119, 6, 0.5);
  border: 1px solid rgba(253, 186, 116, 0.8);
}

/* Level Up Burst */
.qps-levelup-burst {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%) scale(0);
  background: linear-gradient(135deg, #ffd700, #ff9d00);
  color: #1a1a2e;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 1.5px;
  padding: 4px 14px;
  border-radius: 20px;
  white-space: nowrap;
  box-shadow: 0 2px 10px rgba(255, 215, 0, 0.5);
  animation: qsLevelUpBurst 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
  z-index: 1;
}

/* ── Keyframes ── */

@keyframes qsFadeIn {
  to { opacity: 1; }
}

@keyframes qsFadeOut {
  to { opacity: 0; }
}

@keyframes qsBannerSlideDown {
  to { transform: translateY(0); opacity: 1; }
}

@keyframes qsCardIn {
  to { transform: translateY(0); opacity: 1; }
}

@keyframes qsLevelUpBurst {
  0% { transform: translateX(-50%) scale(0); }
  100% { transform: translateX(-50%) scale(1); }
}

@keyframes qsScalePop {
  0% { transform: translateX(-50%) scale(0); }
  60% { transform: translateX(-50%) scale(1.2); }
  100% { transform: translateX(-50%) scale(1); }
}

@keyframes qsMvpGlow {
  0%, 100% { box-shadow: 0 0 20px rgba(255, 215, 0, 0.2), inset 0 0 15px rgba(255, 215, 0, 0.03); }
  50% { box-shadow: 0 0 35px rgba(255, 215, 0, 0.4), inset 0 0 25px rgba(255, 215, 0, 0.06); }
}

@keyframes qsContinueIn {
  to { opacity: 1; }
}

/* ── Mobile Portrait ── */

@media (max-width: 600px) {
  .quest-summary-overlay {
    padding: env(safe-area-inset-top, 16px) 12px env(safe-area-inset-bottom, 16px) 12px;
    align-items: flex-start;
    padding-top: calc(env(safe-area-inset-top, 16px) + 40px);
  }

  .quest-summary-inner {
    gap: 14px;
    padding: 10px;
  }

  .quest-outcome-banner {
    font-size: clamp(22px, 7vw, 40px);
    letter-spacing: 2px;
  }

  .quest-player-cards {
    flex-direction: column;
    align-items: center;
  }

  .qps-card {
    width: 90%;
    max-width: 340px;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 14px;
  }

  .qps-portrait-wrap {
    width: 60px;
    height: 60px;
  }

  .qps-portrait {
    width: 60px;
    height: 60px;
  }

  .qps-info {
    align-items: flex-start;
  }

  .qps-xp-counter {
    font-size: 22px;
  }
}


/* ── P3-2 end screen drumroll (END_SCREEN_V2): one card at a time, the MVP last ── */

.qps-banner-sub {
  font-family: 'League Spartan', sans-serif;
  font-size: 18px;
  color: rgba(255, 255, 255, 0.85);
  text-align: center;
  margin-top: -10px;
}

.qps-reveal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  width: 100%;
}

.qps-reveal-skip {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 16px);
  right: 20px;
  z-index: 2001;
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.8);
  font-family: 'League Spartan', sans-serif;
  font-size: 14px;
  text-decoration: underline;
  cursor: pointer;
}

.qps-reveal-skip:hover,
.qps-reveal-skip:focus-visible { color: #ffffff; }

.qps-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  cursor: pointer; /* a tap moves on early */
  touch-action: manipulation;
}

.qps-tray {
  display: flex;
  gap: 8px;
  min-height: 36px;
  justify-content: center;
  flex-wrap: wrap;
}

.qps-tray-item,
.qps-tray-item .qps-portrait-wrap { width: 36px; height: 36px; }
.qps-tray-item .qps-portrait { width: 36px; height: 36px; border-width: 2px; }
.qps-tray-item.is-mvp .qps-portrait { border-color: #ffd700; }

.qps-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 320px;
  max-width: 90vw;
  min-height: 250px;
  cursor: pointer;
}

.qps-card--v2 {
  width: 320px;
  max-width: 90vw;
  transform: none;
  opacity: 1;
  animation: none;
}

.qps-card--v2.qps-card--enter {
  transform: translateY(40px);
  opacity: 0;
  animation: qsCardIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.qps-card--v2.is-mvp.is-mvp-revealed { animation: qsMvpGlow 2s ease-in-out infinite; }
/* The MVP card slides in like the others, then glows. Without both, the glow rule (more specific) drops qsCardIn and
   the card stays at the --enter start (opacity 0). */
.qps-card--v2.is-mvp.is-mvp-revealed.qps-card--enter {
  animation: qsCardIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards, qsMvpGlow 2s ease-in-out 0.4s infinite;
}
.qps-reveal.is-reduced .qps-card--v2.is-mvp.is-mvp-revealed { animation: none; }
.qps-card--v2.is-mvp .qps-mvp-badge { display: block; }

.qps-you-chip {
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 8px;
  font-size: 11px;
  letter-spacing: 1px;
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
}

.qps-card--v2 .qps-xp-line { align-items: baseline; gap: 10px; }
.qps-level-text { display: inline-block; font-size: 13px; color: rgba(255, 255, 255, 0.7); }
/* The level ticks over at the level-up beat (level_before until then). */
.qps-level-text.is-leveled { color: #ffd700; font-weight: 700; animation: qsLevelTick 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); }
.qps-reveal.is-reduced .qps-level-text.is-leveled { animation: none; }

.qps-mvp-reason {
  font-family: 'League Spartan', sans-serif;
  font-size: 14px;
  text-align: center;
  color: #ffd700;
  font-weight: 600;
}

/* Reward rows: a new move (or level) and a new piece of gear. Flat, 1px line, the player card's 2px icon tile. */
.qps-reward {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  font-family: 'League Spartan', sans-serif;
  text-align: left;
  color: #ffffff;
}

.qps-reward-icon {
  flex: 0 0 38px;
  width: 38px;
  height: 38px;
  box-sizing: border-box;
  border: 2px solid #ffffff;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  overflow: hidden;
}

.qps-reward-icon.has-image { border-width: 1px; }
.qps-reward-glyph { width: 22px; height: 22px; object-fit: contain; filter: brightness(0) invert(1); }
.qps-reward-img { width: 100%; height: 100%; object-fit: cover; }

.qps-reward-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.qps-reward-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }

.qps-reward-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
}

.qps-reward-name {
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  color: #ffffff;
  overflow-wrap: anywhere;
}

.qps-reward-kicker { font-weight: 400; color: rgba(255, 255, 255, 0.82); }

.qps-reward-effect {
  font-size: 12px;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.82);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.qps-reward-meta .qps-loot-tier {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  text-shadow: none;
}

/* A move is the level-up: gold, like the XP. Gear tiles take their tier's line. */
.qps-reward--move .qps-reward-icon,
.qps-reward--level .qps-reward-icon { border-color: #ffd700; color: #ffd700; }
.qps-reward--move .qps-reward-label,
.qps-reward--level .qps-reward-label { color: #ffd700; }
.qps-reward--uncommon .qps-reward-icon { border-color: rgba(74, 229, 74, 0.8); }
.qps-reward--rare .qps-reward-icon { border-color: rgba(255, 215, 0, 0.85); }
.qps-reward--epic .qps-reward-icon { border-color: rgba(196, 160, 255, 0.9); }
.qps-reward--legendary .qps-reward-icon { border-color: rgba(253, 186, 116, 0.9); }

.qps-reward.is-popped { animation: qsFadeUp 0.4s ease-out; }
.qps-reveal.is-reduced .qps-reward.is-popped { animation: none; }

.qps-mvp-eyebrow {
  font-family: 'League Spartan', sans-serif;
  font-size: 28px;
  font-weight: 700;
  color: #ffffff;
  text-align: center;
  letter-spacing: 1px;
}

/* The drumroll moves on by itself; this line fills while a beat holds so nobody waits for a button. */
.qps-progress {
  width: 120px;
  height: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.25);
  overflow: hidden;
}
.qps-progress-fill { width: 100%; height: 100%; background: #ffffff; transform-origin: left center; transform: scaleX(0); }
.qps-progress-fill.is-running { animation-name: qsProgress; animation-timing-function: linear; animation-fill-mode: forwards; }
.qps-reveal.is-reduced .qps-progress { display: none; }
@keyframes qsProgress { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.qps-progress[hidden],
.qps-stage[hidden],
.qps-grid[hidden],
.qps-levelup-line[hidden],
.qps-gear-line[hidden] { display: none; }

/* Results grid. Wide screens: one row up to 4 cards, rows of 3 for 5 and 6, rows of 4 for 7 and 8 (data-cols from
   QuestEndScreenLogic.gridColumns); four go 2x2 below 968px, where one row will not fit. Phones stack (below). */
.qps-inner--v2 { max-width: 1000px; }
/* finish() focuses the grid so keyboard players stay on this screen. accessibility.css rings every :focus-visible,
   and Chrome counts a script focus with nothing focused before as focus-visible, which drew a pale box round the
   grid for mouse and touch players. Ring it only when the last input was a key (EndScreenReveal adds the class). */
.qps-grid:focus { outline: none; box-shadow: none; }
.qps-grid.is-focus-visible:focus { outline: 2px solid #ffffff; outline-offset: 8px; border-radius: 18px; box-shadow: none; }

@media (min-width: 601px) {
  .qps-grid { --qps-cols: 4; --qps-card: 220px; max-width: calc(var(--qps-cols) * var(--qps-card) + (var(--qps-cols) - 1) * 16px); }
  .qps-grid[data-cols="1"] { --qps-cols: 1; }
  .qps-grid[data-cols="2"] { --qps-cols: 2; }
  .qps-grid[data-cols="3"] { --qps-cols: 3; }
  .qps-grid .qps-card--v2 {
    width: min(var(--qps-card), calc((100% - (var(--qps-cols) - 1) * 16px) / var(--qps-cols)));
    padding: 18px 14px;
    gap: 10px;
    justify-content: flex-start;
  }
  .qps-grid .qps-card--v2 .qps-info { gap: 8px; }
  .qps-grid .qps-card--v2 .qps-portrait-wrap,
  .qps-grid .qps-card--v2 .qps-portrait { width: 64px; height: 64px; }
  .qps-grid .qps-card--v2 .qps-xp-counter { font-size: 22px; }
  .qps-grid .qps-reward { padding: 8px 10px; gap: 8px; }
  .qps-grid .qps-reward-icon { flex-basis: 32px; width: 32px; height: 32px; }
  .qps-grid .qps-reward-glyph { width: 18px; height: 18px; }
  .qps-grid .qps-reward-name { font-size: 14px; }
  .qps-grid .qps-reward-effect { display: none; }
}

/* Five or more players: short, wide cards (portrait left), reward rows without their box. */
@media (min-width: 601px) {
  .qps-grid.qps-grid--dense { --qps-card: 300px; }
  .qps-grid--dense .qps-card--v2 { flex-direction: row; align-items: flex-start; padding: 12px; gap: 12px; }
  .qps-grid--dense .qps-card--v2 .qps-portrait-wrap,
  .qps-grid--dense .qps-card--v2 .qps-portrait { width: 48px; height: 48px; }
  .qps-grid--dense .qps-card--v2 .qps-portrait { border-width: 2px; }
  .qps-grid--dense .qps-card--v2 .qps-mvp-badge { font-size: 9px; padding: 2px 6px; }
  .qps-grid--dense .qps-card--v2 .qps-info { align-items: flex-start; gap: 6px; min-width: 0; }
  .qps-grid--dense .qps-card--v2 .qps-name { font-size: 15px; text-align: left; }
  .qps-grid--dense .qps-card--v2 .qps-xp-counter { font-size: 18px; }
  .qps-grid--dense .qps-reward { padding: 0; border: 0; background: none; gap: 8px; }
  .qps-grid--dense .qps-reward-icon { flex-basis: 26px; width: 26px; height: 26px; border-width: 1.5px; border-radius: 6px; }
  .qps-grid--dense .qps-reward-glyph { width: 14px; height: 14px; }
  .qps-grid--dense .qps-reward-icon svg { width: 16px; height: 16px; }
  .qps-grid--dense .qps-reward-body { gap: 1px; }
  .qps-grid--dense .qps-reward-label { font-size: 10px; }
  .qps-grid--dense .qps-reward-name { font-size: 13px; }
  .qps-grid--dense .qps-card--v2 .qps-mvp-reason { font-size: 13px; text-align: left; }
}

/* Tighter stack so the grid, Get my insight and the rating fit a 1280x800 window. */
@media (min-width: 601px) {
  .qps-inner--v2 { gap: 16px; }
  .qps-inner--v2 .quest-outcome-banner { font-size: clamp(28px, 4vw, 44px); }
  .qps-inner--v2 .quest-outcome-banner { padding-top: 8px; padding-bottom: 8px; }
  .qps-inner--v2 .qps-insight-block,
  .qps-inner--v2 .qps-rating-block { margin-top: 4px; }
}

@media (min-width: 601px) and (max-width: 967px) {
  .qps-grid[data-cols="4"] { --qps-cols: 2; }
}

.qps-after-line {
  font-family: 'League Spartan', sans-serif;
  font-size: 16px;
  text-align: center;
  color: #ffffff;
  max-width: 420px;
  opacity: 0;
}

@keyframes qsLevelTick {
  0% { transform: scale(1); }
  50% { transform: scale(1.3); }
  100% { transform: scale(1); }
}

@keyframes qsFadeUp {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 600px) {
  .qps-slot { min-height: 220px; }
  .qps-card--v2 { flex-direction: column; width: 90vw; max-width: 320px; padding: 20px; }
  .qps-grid .qps-card--v2 { flex-direction: row; width: 90%; max-width: 340px; padding: 14px; }
  .qps-card--v2 .qps-info { align-items: center; }
  .qps-grid .qps-card--v2 .qps-info { align-items: flex-start; }
  .qps-grid .qps-card--v2 .qps-mvp-reason { text-align: left; }
  .qps-grid .qps-reward { padding: 8px 10px; }
  .qps-grid .qps-reward-effect { -webkit-line-clamp: 1; }
  .qps-card--v2 .qps-portrait-wrap,
  .qps-card--v2 .qps-portrait { width: 72px; height: 72px; }
  .qps-grid .qps-card--v2 .qps-portrait-wrap,
  .qps-grid .qps-card--v2 .qps-portrait { width: 56px; height: 56px; }
}

/* ════════════════════════════════════════════════════════════
   DEBRIEF WINDOW — Post-summary discussion overlay
   ════════════════════════════════════════════════════════════ */

/* Positioned by JS on #participants-grid center, same as quest start countdown */
.quest-debrief-overlay {
  position: fixed;
  transform: translate(-50%, -50%);
  z-index: 100;
  pointer-events: none;
  opacity: 0;
  animation: qsFadeIn 0.5s ease-out forwards;
}

.qsd-panel {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  padding: 24px 32px;
  width: 380px;
  max-width: 85vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  pointer-events: auto;
}

.qsd-header {
  font-family: 'League Spartan', sans-serif;
  font-size: 18px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.8);
  letter-spacing: 3px;
  text-transform: uppercase;
}

/* Prompt in a blue box */
.qsd-prompt-box {
  width: 100%;
  background: rgba(41, 145, 222, 0.3);
  border: 1px solid rgba(41, 145, 222, 0.45);
  border-radius: 10px;
  padding: 16px 20px;
}

.qsd-prompt {
  font-size: 15px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.9);
  line-height: 1.55;
  margin: 0;
  font-style: italic;
}

.qsd-instructions {
  font-size: 13px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.6);
  line-height: 1.45;
  margin: 0;
  max-width: 320px;
}

/* QUE-1024: typed debrief entry, for players who'd rather type than talk */
.qsd-text-input {
  width: 100%;
  box-sizing: border-box;
  min-height: 72px;
  resize: vertical;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.9);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.45;
}

.qsd-text-input:focus {
  outline: none;
  border-color: rgba(41, 145, 222, 0.7);
}

.qsd-timer {
  font-family: 'League Spartan', sans-serif;
  font-size: 28px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.75);
  letter-spacing: 2px;
  font-variant-numeric: tabular-nums;
}

.qsd-close-btn {
  padding: 8px 28px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.6);
  font-family: 'League Spartan', sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 1px;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.qsd-close-btn:hover,
.qsd-close-btn:active {
  background: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.4);
  color: rgba(255, 255, 255, 0.85);
}

/* Centered in the viewport (phone portrait: no video grid), over the transcript: a solid ground. */
.quest-debrief-overlay.is-viewport .qsd-panel { background: rgba(14, 34, 58, 0.97); }

/* Mobile */
@media (max-width: 600px) {
  .qsd-panel {
    padding: 20px 16px;
    gap: 14px;
    width: 320px;
  }

  .qsd-header {
    font-size: 15px;
    letter-spacing: 2px;
  }

  .qsd-prompt-box {
    padding: 14px 14px;
  }

  .qsd-prompt {
    font-size: 14px;
  }

  .qsd-instructions {
    font-size: 12px;
    max-width: 260px;
  }

  .qsd-timer {
    font-size: 24px;
  }
}


/* ════════════════════════════════════════════════════════════
   POST-QUEST RATING + FEEDBACK BLOCK
   Replaces the old `.qps-continue-btn` on the MVP/quest summary
   overlay. Shares fade-in animation (qsContinueIn) and overall
   dark-glass aesthetic with the rest of the .qps-* surface.
   ════════════════════════════════════════════════════════════ */

.qps-rating-block {
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: min(420px, 92%);
  opacity: 0;
}

.qps-rating-prompt {
  font-family: 'League Spartan', sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.9);
  letter-spacing: 0.5px;
  text-align: center;
  line-height: 1.35;
}

.qps-rating-stars {
  display: flex;
  flex-direction: row;
  gap: 10px;
  justify-content: center;
  align-items: center;
}

.qps-star {
  background: transparent;
  border: none;
  padding: 4px;
  cursor: pointer;
  line-height: 0;
  border-radius: 8px;
  transition: transform 0.15s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.qps-star:hover,
.qps-star:focus-visible {
  transform: scale(1.08);
  outline: none;
}

.qps-star:focus-visible {
  box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.45);
}

.qps-star svg {
  width: 36px;
  height: 36px;
  /* Default (unselected): outline-only feel via low-opacity stroke + fill */
  fill: rgba(255, 255, 255, 0.18);
  stroke: rgba(255, 255, 255, 0.55);
  stroke-width: 1.2;
  transition: fill 0.18s ease, stroke 0.18s ease, transform 0.15s ease;
}

.qps-star.is-hover-filled svg {
  fill: rgba(255, 215, 0, 0.55);
  stroke: rgba(255, 215, 0, 0.9);
}

.qps-star.is-selected svg {
  fill: rgba(255, 215, 0, 0.95);
  stroke: rgba(255, 215, 0, 1);
  filter: drop-shadow(0 0 6px rgba(255, 215, 0, 0.45));
}

.qps-feedback-textarea {
  width: 100%;
  min-height: 72px;
  max-height: 160px;
  padding: 12px 14px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 10px;
  color: rgba(255, 255, 255, 0.95);
  font-family: 'League Spartan', sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.45;
  resize: vertical;
  outline: none;
  transition: border-color 0.18s ease, background 0.18s ease;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.qps-feedback-textarea::placeholder {
  color: rgba(255, 255, 255, 0.45);
}

.qps-feedback-textarea:focus {
  border-color: rgba(41, 145, 222, 0.7);
  background: rgba(0, 0, 0, 0.5);
}

.qps-send-feedback-btn {
  margin-top: 4px;
  padding: 12px 38px;
  background: rgba(41, 145, 222, 0.85);
  border: 1px solid rgba(41, 145, 222, 1);
  border-radius: 10px;
  color: white;
  font-family: 'League Spartan', sans-serif;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 1px;
  cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, opacity 0.2s ease, transform 0.1s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.qps-send-feedback-btn:hover:not(:disabled),
.qps-send-feedback-btn:active:not(:disabled) {
  background: rgba(41, 145, 222, 1);
  border-color: rgba(70, 165, 232, 1);
}

.qps-send-feedback-btn:active:not(:disabled) {
  transform: translateY(1px);
}

.qps-send-feedback-btn:disabled {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.4);
  cursor: not-allowed;
}

.qps-skip-link {
  margin-top: 2px;
  padding: 6px 10px;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.55);
  font-family: 'League Spartan', sans-serif;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color 0.18s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.qps-skip-link:hover,
.qps-skip-link:focus-visible {
  color: rgba(255, 255, 255, 0.85);
  outline: none;
}

/* P3-3 "Get my insight": shown above the rating block once the server offers it. */
.qps-insight-block {
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(420px, 92%);
  opacity: 0;
}

.qps-insight-block[hidden] {
  display: none;
}

.qps-insight-btn {
  padding: 12px 38px;
  background: rgba(41, 145, 222, 0.85);
  border: 1px solid rgba(41, 145, 222, 1);
  border-radius: 10px;
  color: white;
  font-family: 'League Spartan', sans-serif;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 1px;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.qps-insight-btn:disabled {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.55);
  cursor: default;
}

.qps-insight-status {
  min-height: 1.2em;
  font-family: 'League Spartan', sans-serif;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  text-align: center;
}

.qps-insight-status a {
  color: rgba(120, 190, 240, 1);
}

/* Mobile portrait: tighten spacing + slightly smaller stars */
@media (max-width: 600px) {
  .qps-rating-block {
    margin-top: 18px;
    gap: 12px;
    width: 100%;
  }

  .qps-rating-prompt {
    font-size: 15px;
  }

  .qps-rating-stars {
    gap: 8px;
  }

  .qps-star svg {
    width: 32px;
    height: 32px;
  }

  .qps-feedback-textarea {
    font-size: 16px;
    min-height: 64px;
  }

  .qps-send-feedback-btn {
    padding: 11px 30px;
    font-size: 15px;
  }
}

/* ============================================================================
   QUE-154 — On-screen quest objectives, rendered as pill chips INSIDE the
   .dice-and-timer-container top bar, occupying the .dice-area's territory.
   ----------------------------------------------------------------------------
   The strip is absolutely positioned inside the bar between the left padding
   and the chat button + timer-area on the right (timer-area `min-width: 140px`
   plus the ~50px chat button plus the 15px bar gap × 2 ≈ 220px reserved).
   Chips fade out behind the chat button via a right-edge mask.

   When a dice pool appears in .dice-area, ObjectivesManager adds the
   `dice-active` modifier and the strip slides right + fades — the dice take
   over the visual space for the duration of the roll. When dice clear, the
   modifier is removed and the strip slides back.

   Layout:

     [chips..............faded][chat][tension|portal]   <- bar (10vh)
     participants grid                                    <- no offset needed
   ============================================================================ */

/* Class retained as a state marker so other surfaces can react if needed
   (e.g. legacy :has selectors). Layout impact is now zero — chips live
   inside the bar's existing height. */
.dice-and-timer-container.has-objectives {
  /* no-op — strip is absolutely positioned inside the bar */
}

/* Chip strip — sits in the left portion of the bar and STOPS before the
   chat button. The scroll container itself ends there (not full bar width)
   so chips fade to fully transparent into the blue bar background, never
   bleeding into the chat button or timer-area. When dice are active, the
   strip slides right off-frame (translateX + fade) so dice take the stage. */
/* Make .dice-area a positioning context for the strip — strip is now a
   child of dice-area so it can never extend past dice-area's right edge
   (which is where the threat tracker / chat / timers begin). Clip the
   slide-out animation so chips can't escape into the neighboring elements
   during the transform. */
.dice-area {
  position: relative;
  overflow: hidden;
}

.objectives-strip {
  position: absolute;
  inset: 0;                              /* fill the dice-area exactly */
  display: flex;
  justify-content: flex-start;           /* anchor left, extend rightward */
  align-items: center;
  pointer-events: auto;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  z-index: 1;                            /* above empty dice-area, under any future dice content */
  /* Fade chips solid → transparent across the last 60px of dice-area so
     they land on the bar's blue background BEFORE the threat tracker. */
  mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 60px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 60px), transparent 100%);
  /* Return animation (chips sliding back in after a roll resolves): a smooth
     decelerate so they ease into place rather than land hard. */
  transition:
    transform 0.55s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.45s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
  /* Hint to compositor: keep the element on its own layer so the slide
     doesn't have to repaint the masked text every frame. */
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
}

/* Dice pool active — chips slide right (toward the chat button) and fade.
   They tuck behind the right-side controls; once the roll resolves, the
   modifier is removed and they slide back into place.
   Use a longer-distance translate + opacity fading FASTER than position so
   chips become visually gone before they reach the controls' footprint —
   reads as a graceful exit instead of a translucent flyby. Easing here is
   a soft accelerate (ease-in-ish) so the leave feels weighty, not abrupt. */
.objectives-strip.dice-active {
  transform: translate3d(calc(100% + 60px), 0, 0);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 0.65s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 0.32s cubic-bezier(0.4, 0, 1, 1);
}

/* No layout offsets needed — the strip now lives inside the bar, so the
   participants grid and notification center can keep their default
   positioning relative to the bar's bottom edge. */
.objectives-strip::-webkit-scrollbar { display: none; }

.objectives-chip-list {
  list-style: none;
  margin: 0;
  padding: 0 56px 0 0;                   /* room for the right fade gutter (matches mask) */
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  align-items: center;
}

.objective-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: rgba(255, 255, 255, 0.85);
  border: 1.5px solid #2991de;           /* QuestWorks primary blue */
  border-radius: 999px;
  color: #296590;
  font-size: 17px;                       /* QUE-952: one Team Prompt, bigger text */
  font-weight: 600;
  line-height: 1;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.10);
  transition: background-color 250ms ease, border-color 250ms ease, color 250ms ease, transform 200ms ease;
  white-space: nowrap;
  list-style: none;                      /* defensive — UA UL/LI reset */
  /* Center on cap-height + alphabetic baseline, not the font's full ascent/
     descent box — otherwise objective text without a descender letter sits
     visibly higher than text that has one. No-op where unsupported. */
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}
.objective-chip::marker { content: none; }

.objective-chip-text {
  white-space: nowrap;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

/* Bonus indicator is now expressed as a gold pill tint rather than a star icon
   — hide the star span the renderer still emits. Keep the element in the DOM
   for screen readers / a11y label. */
.objective-chip-bonus {
  display: none;
}

/* Bonus chip: muted antique-gold/champagne tint with white text. Border
   stays the consistent QuestWorks blue (#2991de) — fill carries the
   reward signal, stroke ties the row together visually. */
.objective-chip.is-bonus {
  background: rgba(217, 164, 78, 0.85);
  color: #fff;
}
.objective-chip.is-complete {
  background: #1f9d55;
  border-color: #1f9d55;
  color: #fff;
}
/* Completed wins over bonus tint — green pill for both core and bonus when
   completed, matching the post-quest summary language. */
.objective-chip.is-bonus.is-complete {
  background: #1f9d55;
  border-color: #1f9d55;
}
.objective-chip.is-complete .objective-chip-text {
  text-decoration: line-through;
  text-decoration-color: rgba(255, 255, 255, 0.55);
}

/* Failed/missed objective — red pill, wins over bonus tint like complete does. */
.objective-chip.is-missed,
.objective-chip.is-bonus.is-missed {
  background: #c53030;
  border-color: #c53030;
  color: #fff;
}
.objective-chip.is-missed .objective-chip-text {
  text-decoration: line-through;
  text-decoration-color: rgba(255, 255, 255, 0.55);
}

@keyframes objective-chip-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
.objective-chip.just-completed {
  animation: objective-chip-pop 700ms ease-out;
}

@media (max-width: 900px) {
  /* Per QUE-154 product call: chips hidden on mobile. The bar already keeps
     its original height (strip is absolute), so no bar overrides are needed —
     just hide the strip itself. */
  .objectives-strip { display: none; }
}

/* ----------------------------------------------------------------------------
   Post-quest summary objectives block (rendered inside QuestSummary overlay).
   Same chip language as in-quest: completed = green pill, missed = red pill,
   white text always. Pending state shouldn't appear here (session_end always
   resolves everything to one bucket).
   ---------------------------------------------------------------------------- */

.objectives-summary {
  margin: 14px 0 18px;
  padding: 12px 14px;
  background: #ffffff;
  border: 1px solid #dce4ec;
  border-radius: 10px;
}
.objectives-summary-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #296590;
  margin-bottom: 10px;
}
.objectives-summary-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.objectives-summary-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 6px 11px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  align-self: flex-start;
  color: #fff;
  list-style: none;
  /* Center on cap-height + alphabetic baseline, not the font's full ascent/
     descent box — otherwise objective text without a descender letter sits
     visibly higher than text that has one. No-op where unsupported. */
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}
.objectives-summary-item::marker { content: none; }
.objectives-summary-item .objective-icon {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
}
.objectives-summary-item .objective-text {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}
.objectives-summary-item.is-complete {
  background: #1f9d55;
}
.objectives-summary-item.is-missed {
  background: #c0392b;
}
.objectives-summary-item .objective-bonus-pill {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 2px 5px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
  margin-left: 4px;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}
.objectives-summary-counts {
  margin-top: 12px;
  font-size: 12px;
  color: #296590;
  font-variant-numeric: tabular-nums;
}

/* ===================================================================
   QUE-433: "Connecting…" state on the local self-tile + mic button.
   Reuses the shared @keyframes spin (defined ~L2484) — do NOT redefine.
   Overlay sits at z-index 9, below the .participant-name tag (z-index 10),
   so the green "(You)" name stays legible.
   =================================================================== */
.participant-connecting-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  z-index: 9;
  text-align: center;
  padding: 8px;
  transition: opacity 0.4s ease;
}

.participant-connecting-overlay.fading {
  opacity: 0;
}

.connecting-spinner {
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 4px;
}

.connecting-text {
  font-size: 14px;
  font-weight: 600;
}

.connecting-subtext {
  font-size: 11px;
  opacity: 0.8;
}

/* Success state: green scrim + ✓ + "You're live" */
.participant-connecting-overlay.is-live {
  background: rgba(40, 167, 69, 0.85);
}

.connecting-check {
  font-size: 28px;
  color: #fff;
  animation: connecting-pop 0.3s ease;
}

@keyframes connecting-pop {
  0% { transform: scale(0.4); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* Slow / "still connecting" state: amber copy, overlay stays up. */
.participant-connecting-overlay.is-slow .connecting-text,
.participant-connecting-overlay.is-slow .connecting-subtext {
  color: #ffc107;
}

/* Terminal failure (permission denied / no mic / OS-blocked): red scrim,
   distinct non-transient copy. Overlay stays up so the player can act. */
.participant-connecting-overlay.is-failed {
  background: rgba(176, 32, 32, 0.85);
}

.connecting-fail-icon {
  width: 28px;
  height: 28px;
  line-height: 26px;
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  border: 2px solid #fff;
  border-radius: 50%;
  text-align: center;
}

/* Mic-button secondary cue while connecting: pulsing dot + reduced opacity.
   Does NOT disable the button — players keep mute/unmute intent. */
#toggle-audio-btn.connecting {
  position: relative;
  opacity: 0.7;
}

#toggle-audio-btn.connecting::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ffc107;
  animation: connecting-dot-pulse 1.2s ease-in-out infinite;
}

@keyframes connecting-dot-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.4); opacity: 0.4; }
}

/* Mobile: drop the subtext, smaller spinner/text, frosted scrim. */
@media (max-width: 768px) {
  .participant-connecting-overlay .connecting-subtext {
    display: none;
  }
  .participant-connecting-overlay {
    background: rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
  }
  /* Keep the green success scrim solid on mobile too. */
  .participant-connecting-overlay.is-live {
    background: rgba(40, 167, 69, 0.85);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .connecting-spinner {
    width: 20px;
    height: 20px;
  }
  .connecting-text {
    font-size: 12px;
  }
}

/* Reduced motion: freeze the spinner, ✓ pop, and mic dot — keep copy/color. */
@media (prefers-reduced-motion: reduce) {
  .connecting-spinner,
  .connecting-check,
  #toggle-audio-btn.connecting::after {
    animation: none;
  }
}

/* Volume panel (VolumeMixer.js): same card as device settings, one row per
   source with its level on the right. */
.volume-mix-row label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.volume-mix-value {
  font-variant-numeric: tabular-nums;
  text-transform: none;
  letter-spacing: 0;
}

.volume-mix-row input[type="range"] {
  width: 100%;
  accent-color: #ffffff;
  cursor: pointer;
}

/* The rare adjustment that raises the pool after the receipt. */
.risk-why-moves.risk-why-item--against .risk-why-glyph {
  background: #EF4444;
}
