/* ============================================================
   AutoBoost — custom edge-case overrides
   Pure CSS, no Tailwind directives.
   Committed to git; Propshaft serves without a build step.
   ============================================================ */

/* ── Layout: sidebar offset ──────────────────────────────── */
@media (min-width: 1024px) {
  body > main {
    margin-left: 14rem; /* sidebar w-56 = 14rem */
  }
}

/* ── Dark mode: sidebar background & text ────────────────── */
/* Apple-esque neutral dark gray — matches the navbar (gray-900).  */
/* Autoboost brand colors used ONLY for accents (active border).   */
/* Rules sit outside any @layer so they win the cascade            */
/* regardless of Tailwind utility ordering.                        */
.dark .sidebar {
  background-color: #111827; /* Tailwind gray-900 — matches navbar */
  border-right-color: rgba(255, 255, 255, 0.06);
}

.dark .sidebar-link {
  color: rgba(255, 255, 255, 0.70);
  border-left: 2px solid rgba(255, 255, 255, 0.08);
}

.dark .sidebar-link:hover {
  background-color: rgba(255, 255, 255, 0.05);
  color: #ffffff;
}

.dark .sidebar-link-active {
  background-color: rgba(71, 174, 230, 0.10); /* accent blue at low alpha */
  color: #ffffff;
  border-color: #47aee6; /* accent blue — autoboost brand accent */
}

.dark .sidebar-section {
  color: rgba(255, 255, 255, 0.40);
}

/* ── Sidebar: btn-primary always white text ─────────────── */
.sidebar .btn-primary {
  color: #ffffff !important;
  background-color: var(--color-brand) !important;
}

.sidebar .btn-primary:hover {
  background-color: var(--color-brand-dark) !important;
  color: #ffffff !important;
}

.dark .sidebar .btn-primary {
  background-color: #47aee6 !important; /* accent — pops on the dark gray bg */
}

.dark .sidebar .btn-primary:hover {
  background-color: #3a9ad0 !important;
}

/* ── Notification waterfall: progress bar ──────────────────── */
@keyframes notif-progress {
  0%   { width: 0%; background-position: 0% 50%; }
  100% { width: 100%; background-position: 100% 50%; }
}

.notif-progress-bar {
  position: absolute;
  /* Pinned to the TOP border of the notification — the bottom was
     overlapping the new action-chip row (Retry / Pause / Dismiss /
     etc.) added in the notification-actions feature. */
  top: 0;
  left: 0;
  height: 2px;
  width: 0%;
  background: linear-gradient(90deg, #47aee6, #50b744, #f6b200, #d67ba6);
  background-size: 300% 100%;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.notif-progress-bar.active {
  opacity: 1;
  animation: notif-progress 0.15s ease-out forwards;
}

/* ── Notification waterfall: read celebration pulse ────────── */
@keyframes notif-read-pulse {
  0%   { background-color: rgba(71, 174, 230, 0.12); }
  100% { background-color: transparent; }
}

@keyframes notif-read-pulse-dark {
  0%   { background-color: rgba(71, 174, 230, 0.15); }
  100% { background-color: transparent; }
}

.notif-read-celebrate {
  animation: notif-read-pulse 0.1s ease-out forwards;
}

.dark .notif-read-celebrate {
  animation-name: notif-read-pulse-dark;
}

/* ── Caption popover: slide-up animation ─────────────────── */
@keyframes caption-slide-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.caption-popover {
  animation: caption-slide-up 0.18s ease-out forwards;
}

.caption-popover-inner {
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 0.75rem;
  box-shadow: 0 10px 25px -5px rgba(0,0,0,0.15), 0 4px 10px -5px rgba(0,0,0,0.1);
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  line-height: 1.625;
  color: #374151;
}

.caption-popover-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.caption-popover-label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9ca3af;
}

.caption-popover-close {
  font-size: 0.75rem;
  color: #9ca3af;
  cursor: pointer;
  padding: 0 0.25rem;
  transition: color 0.15s;
}

.caption-popover-close:hover {
  color: #374151;
}

.caption-popover-body {
  max-height: 10rem;
  overflow-y: auto;
  color: #374151;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Dark mode (class-based) */
.dark .caption-popover-inner {
  background: #1f2937;
  border-color: #374151;
  color: #d1d5db;
}

.dark .caption-popover-close:hover {
  color: #f3f4f6;
}

.dark .caption-popover-body {
  color: #d1d5db;
}

/* ── AB-035b M5: horizontal scroll affordance ─────────────────
   Tables wrapped in overflow-x-auto on mobile hide the fact that
   they scroll. `.scroll-x-shadow` paints a fading shadow on the
   left/right edges that tucks in when the container is scrolled to
   that edge. Classic Lea Verou scroll-shadow trick using
   background-attachment: local, scroll on the same element.

   Apply by adding `scroll-x-shadow` alongside `overflow-x-auto` on
   the wrapping <div>.
   ============================================================ */
.scroll-x-shadow {
  background:
    /* Left edge shadow - fades in when scrolled right */
    linear-gradient(90deg, rgba(0,0,0,0.12), rgba(0,0,0,0)) left center / 1.25rem 100% no-repeat local,
    /* Right edge shadow - fades in when more content to the right */
    linear-gradient(-90deg, rgba(0,0,0,0.12), rgba(0,0,0,0)) right center / 1.25rem 100% no-repeat local,
    /* Left edge mask - hides shadow when scrolled to start */
    linear-gradient(90deg, rgba(255,255,255,1), rgba(255,255,255,0)) left center / 1rem 100% no-repeat scroll,
    /* Right edge mask - hides shadow when scrolled to end */
    linear-gradient(-90deg, rgba(255,255,255,1), rgba(255,255,255,0)) right center / 1rem 100% no-repeat scroll;
}

.dark .scroll-x-shadow {
  background:
    linear-gradient(90deg, rgba(255,255,255,0.14), rgba(255,255,255,0)) left center / 1.25rem 100% no-repeat local,
    linear-gradient(-90deg, rgba(255,255,255,0.14), rgba(255,255,255,0)) right center / 1.25rem 100% no-repeat local,
    linear-gradient(90deg, rgb(17,24,39), rgba(17,24,39,0)) left center / 1rem 100% no-repeat scroll,
    linear-gradient(-90deg, rgb(17,24,39), rgba(17,24,39,0)) right center / 1rem 100% no-repeat scroll;
}

/* ============================================================
   /insights live streaming (feat/insights-live-streaming)
   - trace-step-enter: per-step slide+fade-in animation when
     InsightReportStep#broadcast_step appends a new step into
     #insight_<id>_trace_steps. Gated on prefers-reduced-motion
     so motion-sensitive users get instant insertion.
   - badge-running: gentler pulse on the running status badge
     than Tailwind's default animate-pulse — easier on the eyes
     during a 15-90s run.
   - view-transition-name: insight-tile-<agent> + insight-<id>
     contract: dashboard tile morphs into show page header on
     navigation when both sides declare matching names (set
     inline via style="view-transition-name: ...;" in views).
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {
  @keyframes trace-step-enter {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
  }
  .trace-step-enter {
    animation: trace-step-enter 240ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  @keyframes pulse-running {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.65; }
  }
  .badge-running {
    animation: pulse-running 2.2s ease-in-out infinite;
  }

  /* Insight card "settle" glow — fires when a card is swapped into the
     DOM via InsightBroadcaster.tile_completed.
     insight-glow-controller.js adds .insight-glow-active on mount and
     strips both classes when the animation ends. */
  @keyframes insight-settle-glow {
    0% {
      box-shadow: 0 0 0 4px rgba(71, 174, 230, 0.45),
                  0 8px 24px -8px rgba(71, 174, 230, 0.35);
      transform: translateY(-2px);
    }
    50% {
      box-shadow: 0 0 0 6px rgba(80, 183, 68, 0.30),
                  0 12px 32px -10px rgba(80, 183, 68, 0.25);
      transform: translateY(-1px);
    }
    100% {
      box-shadow: 0 0 0 0 rgba(80, 183, 68, 0), 0 0 0 0 rgba(80, 183, 68, 0);
      transform: none;
    }
  }
  .insight-glow.insight-glow-active {
    animation: insight-settle-glow 1.1s cubic-bezier(0.16, 1, 0.3, 1) both;
    will-change: box-shadow, transform;
  }
}

/* ===================================================================
   Curator — Apple-esque canvas (white-dominant, contained backdrop)
   =================================================================== */

/* Outer canvas: self-contained white surface with faint tinted
   gradient + soft border + soft shadow. overflow-hidden + isolation
   guarantee every effect inside stays bounded to this container. */
.curator-canvas {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: 1.5rem;
  background: linear-gradient(135deg, #ffffff 0%, #fbfcff 50%, #f6f9ff 100%);
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.02),
    0 8px 24px rgba(15, 30, 80, 0.04);
  padding: 2rem 1.5rem;
  min-height: 360px;
}

@media (min-width: 640px) {
  .curator-canvas {
    padding: 3.5rem 3rem;
    border-radius: 2rem;
  }
}

.dark .curator-canvas {
  background: linear-gradient(135deg, #0f1117 0%, #131520 50%, #181a26 100%);
  border-color: rgba(255, 255, 255, 0.06);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.2),
    0 8px 24px rgba(0, 0, 0, 0.4);
}

/* Faded dot grid — extremely subtle, masked to fade at edges so the
   grid never reaches the canvas border. */
.curator-canvas::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(39, 56, 123, 0.06) 1px, transparent 0);
  background-size: 22px 22px;
  mask-image: radial-gradient(ellipse 80% 70% at center, black 0%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at center, black 0%, transparent 75%);
  z-index: 0;
  pointer-events: none;
}

.dark .curator-canvas::before {
  background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.06) 1px, transparent 0);
}

/* Drifting blurry orbs — heavy blur + low opacity + very large radius.
   They read as colored light, not as shapes. */
.curator-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(110px);
  z-index: 0;
  pointer-events: none;
  will-change: transform;
}

.curator-orb-1 {
  width: 520px;
  height: 520px;
  background: radial-gradient(circle, rgba(71, 174, 230, 0.30) 0%, transparent 60%);
  top: -180px;
  left: -140px;
  animation: curator-orb-drift-1 22s ease-in-out infinite;
}

.curator-orb-2 {
  width: 460px;
  height: 460px;
  background: radial-gradient(circle, rgba(39, 56, 123, 0.20) 0%, transparent 60%);
  bottom: -200px;
  right: -120px;
  animation: curator-orb-drift-2 26s ease-in-out infinite;
}

.curator-orb-3 {
  width: 400px;
  height: 400px;
  background: radial-gradient(circle, rgba(214, 123, 166, 0.16) 0%, transparent 60%);
  top: 50%;
  left: 50%;
  animation: curator-orb-drift-3 30s ease-in-out infinite;
}

.dark .curator-orb-1 { background: radial-gradient(circle, rgba(71, 174, 230, 0.18) 0%, transparent 60%); }
.dark .curator-orb-2 { background: radial-gradient(circle, rgba(98, 116, 184, 0.16) 0%, transparent 60%); }
.dark .curator-orb-3 { background: radial-gradient(circle, rgba(214, 123, 166, 0.10) 0%, transparent 60%); }

@keyframes curator-orb-drift-1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(60px, 40px) scale(1.08); }
}

@keyframes curator-orb-drift-2 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-50px, -40px) scale(1.06); }
}

@keyframes curator-orb-drift-3 {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(calc(-50% + 40px), calc(-50% + 30px)) scale(1.05); }
}

@media (prefers-reduced-motion: reduce) {
  .curator-orb        { animation: none; }
  .curator-empty-icon { animation: none; }
}

/* Content layer — always above the backdrop. */
.curator-content {
  position: relative;
  z-index: 1;
}

/* Empty-state icon — slow gentle float. */
@keyframes curator-sparkle-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}
.curator-empty-icon {
  animation: curator-sparkle-float 6s ease-in-out infinite;
}

/* GPU-accelerate the carousel track for smooth translateX. */
[data-curator-carousel-target="track"] {
  will-change: transform;
}

/* ── Curator live stream: status chip animations ───────────── */

@keyframes curator-chip-enter {
  from { opacity: 0; transform: translateY(12px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

@keyframes curator-chip-exit {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-8px) scale(0.97); }
}

@media (prefers-reduced-motion: no-preference) {
  .curator-chip-enter {
    animation: curator-chip-enter 350ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  .curator-chip-exit {
    animation: curator-chip-exit 300ms cubic-bezier(0.4, 0, 0.6, 1) both;
  }
}
