/* Custom Design System & Utility Enhancements for Dreamsmore AI */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@500;600;700&display=swap');

:root {
  --color-primary: #003d9b;
  --color-primary-container: #0052cc;
  --color-on-primary-container: #c4d2ff;
  --color-surface: #f9f9f9;
  --color-surface-bright: #ffffff;
  --color-surface-container-low: #f3f3f4;
  --color-surface-container-lowest: #ffffff;
  --color-surface-container: #eeeeee;
  --color-surface-container-high: #e8e8e8;
  --color-surface-container-highest: #e2e2e2;
  --color-on-surface: #1a1c1c;
  --color-on-surface-variant: #434654;
  --color-secondary: #555f6c;
  --color-secondary-container: #d9e3f2;
  --color-slate-border: #D0D5DD;
  --color-outline: #737685;
  --glass-bg: rgba(255, 255, 255, 0.75);
  --glass-border: rgba(255, 255, 255, 0.6);
  --card-shadow: 0 4px 20px -2px rgba(0, 30, 80, 0.08);
}

.dark {
  --color-primary: #5b92ff;
  --color-primary-container: #0040a2;
  --color-on-primary-container: #dae2ff;
  --color-surface: #0f131a;
  --color-surface-bright: #171c26;
  --color-surface-container-low: #151a24;
  --color-surface-container-lowest: #1b212e;
  --color-surface-container: #222938;
  --color-surface-container-high: #2a3345;
  --color-surface-container-highest: #333d52;
  --color-on-surface: #f0f2f8;
  --color-on-surface-variant: #b0b8c8;
  --color-secondary: #94a3b8;
  --color-secondary-container: #1e293b;
  --color-slate-border: #2d3748;
  --color-outline: #64748b;
  --glass-bg: rgba(21, 26, 36, 0.75);
  --glass-border: rgba(255, 255, 255, 0.1);
  --card-shadow: 0 4px 25px -2px rgba(0, 0, 0, 0.4);
}

body {
  font-family: 'Inter', sans-serif;
  background-color: var(--color-surface);
  color: var(--color-on-surface);
  transition: background-color 0.3s ease, color 0.3s ease;
  overflow-x: hidden;
}

/* Glassmorphism Panel */
.glass-panel {
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--glass-border);
}

/* Creative Animated Aurora Mesh Hero Banner Background */
.creative-hero-bg {
  position: relative;
  background:
    linear-gradient(100deg, rgba(0, 18, 51, 0.62) 0%, rgba(0, 18, 51, 0.44) 40%, rgba(0, 30, 90, 0.20) 66%, rgba(0, 40, 120, 0.05) 100%),
    url('/assets/img/01-hero-collage.webp') center right / cover no-repeat,
    linear-gradient(135deg, #001233 0%, #002878 35%, #0052cc 70%, #0077ff 100%);
  overflow: hidden;
  box-shadow: 0 20px 40px -10px rgba(0, 60, 180, 0.35);
}

@media (max-width: 767px) {
  .creative-hero-bg {
    background:
      linear-gradient(165deg, rgba(0, 18, 51, 0.72) 0%, rgba(0, 18, 51, 0.6) 55%, rgba(0, 40, 120, 0.42) 100%),
      url('/assets/img/01-hero-collage.webp') center / cover no-repeat,
      linear-gradient(135deg, #001233 0%, #002878 35%, #0052cc 70%, #0077ff 100%);
  }
}

/* With a lighter scrim the copy carries its own contrast. Two stacked shadows:
   a tight dark one for edge definition, a wide one to lift text off busy areas. */
.creative-hero-bg h1,
.creative-hero-bg p,
.creative-hero-bg .hero-pop {
  text-shadow: 0 1px 2px rgba(0, 8, 24, 0.9), 0 4px 18px rgba(0, 8, 24, 0.65);
}

.creative-hero-bg h1 span {
  filter: drop-shadow(0 2px 10px rgba(0, 10, 40, 0.75));
}

.creative-hero-bg::before {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: radial-gradient(circle at 30% 30%, rgba(0, 240, 255, 0.25) 0%, transparent 40%),
              radial-gradient(circle at 75% 70%, rgba(130, 0, 255, 0.3) 0%, transparent 45%),
              radial-gradient(circle at 50% 80%, rgba(0, 255, 170, 0.2) 0%, transparent 40%);
  animation: rotateAurora 18s linear infinite;
  pointer-events: none;
}

@keyframes rotateAurora {
  0% { transform: rotate(0deg) scale(1); }
  50% { transform: rotate(180deg) scale(1.1); }
  100% { transform: rotate(360deg) scale(1); }
}

/* Levitating & Bouncing Card Physics Animations */
@keyframes levitateBounce1 {
  0%, 100% {
    transform: translateY(0px) rotate(-3deg) scale(1);
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4), 0 0 20px rgba(0, 240, 255, 0.3);
  }
  50% {
    transform: translateY(-16px) rotate(-1deg) scale(1.03);
    box-shadow: 0 30px 50px rgba(0, 0, 0, 0.5), 0 0 35px rgba(0, 240, 255, 0.6);
  }
}

@keyframes levitateBounce2 {
  0%, 100% {
    transform: translateY(0px) rotate(4deg) scale(1);
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4), 0 0 20px rgba(160, 32, 240, 0.3);
  }
  50% {
    transform: translateY(-20px) rotate(6deg) scale(1.04);
    box-shadow: 0 32px 55px rgba(0, 0, 0, 0.55), 0 0 40px rgba(160, 32, 240, 0.65);
  }
}

@keyframes levitateBounce3 {
  0%, 100% {
    transform: translateY(0px) rotate(-2deg) scale(1);
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4), 0 0 20px rgba(0, 255, 170, 0.3);
  }
  50% {
    transform: translateY(-14px) rotate(-4deg) scale(1.03);
    box-shadow: 0 28px 45px rgba(0, 0, 0, 0.5), 0 0 30px rgba(0, 255, 170, 0.6);
  }
}

@keyframes levitateBounce4 {
  0%, 100% {
    transform: translateY(0px) rotate(5deg) scale(1);
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4), 0 0 20px rgba(255, 200, 0, 0.3);
  }
  50% {
    transform: translateY(-18px) rotate(3deg) scale(1.04);
    box-shadow: 0 30px 50px rgba(0, 0, 0, 0.55), 0 0 35px rgba(255, 200, 0, 0.6);
  }
}

.levitate-card-1 {
  animation: levitateBounce1 4.5s ease-in-out infinite;
  transition: transform 0.3s ease;
}

.levitate-card-2 {
  animation: levitateBounce2 5.2s ease-in-out infinite 0.6s;
  transition: transform 0.3s ease;
}

.levitate-card-3 {
  animation: levitateBounce3 4.8s ease-in-out infinite 1.2s;
  transition: transform 0.3s ease;
}

.levitate-card-4 {
  animation: levitateBounce4 5.5s ease-in-out infinite 0.3s;
  transition: transform 0.3s ease;
}

.levitate-card-1:hover, .levitate-card-2:hover, .levitate-card-3:hover, .levitate-card-4:hover {
  animation-play-state: paused;
  transform: scale(1.08) translateY(-10px) z-index: 30;
}

/* Custom Scrollbar */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background-color: rgba(115, 118, 133, 0.3);
  border-radius: 9999px;
}
::-webkit-scrollbar-thumb:hover {
  background-color: rgba(115, 118, 133, 0.6);
}

/* Shimmer animation */
@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

.shimmer-bg {
  background: linear-gradient(90deg, 
    rgba(255,255,255,0) 0%, 
    rgba(0, 82, 204, 0.15) 50%, 
    rgba(255,255,255,0) 100%);
  background-size: 200% 100%;
  animation: shimmer 2s infinite;
}

/* Material Symbols */
.material-symbols-outlined {
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  user-select: none;
}

.icon-fill {
  font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}

/* Tab Page Visibility */
.view-page {
  display: none;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.view-page.active-view {
  display: block;
  opacity: 1;
  transform: translateY(0);
}

/* Modal Overlay */
.modal-overlay {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.modal-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.modal-card {
  transform: scale(0.95) translateY(10px);
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.modal-overlay.open .modal-card {
  transform: scale(1) translateY(0);
}

/* Safe areas: keep the bottom nav and toasts clear of the Android gesture bar
   and the iPhone home indicator when the page runs full-bleed (viewport-fit=cover,
   the installed app, or the Play Store wrapper). The nav already carries the
   pb-safe class; it was never defined until now. */
.pb-safe {
  padding-bottom: max(0.75rem, env(safe-area-inset-bottom, 0px));
}

/* Toast Notifications */
#toast-container {
  position: fixed;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  right: 20px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

@media (min-width: 768px) {
  #toast-container {
    bottom: 24px;
  }
}

.toast-msg {
  pointer-events: auto;
  animation: slideUpToast 0.3s ease forwards;
}

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

/* Toggled from app.js to show/hide header chrome by auth state.
   Needs !important because Tailwind's utility classes on the same elements
   (flex, md:flex) also set `display` and the CDN build loads after this file,
   so without it the Sign In button stayed visible while signed in. */
.chrome-hidden {
  display: none !important;
}

/* ---------------------------------------------------------------------------
   Generation waiting state
   A video takes ~2 minutes. The old screen was a bare spinner with invented
   copy ("8K on GPU farm"), which was both dull and untrue. This gives honest
   stage feedback with enough motion to not feel frozen.
--------------------------------------------------------------------------- */
.gen-orb {
  position: absolute;
  border-radius: 9999px;
  filter: blur(48px);
  opacity: 0.35;
  pointer-events: none;
}
.gen-orb-a {
  width: 220px; height: 220px;
  background: var(--color-primary, #0052cc);
  top: -60px; left: -50px;
  animation: gen-drift-a 9s ease-in-out infinite alternate;
}
.gen-orb-b {
  width: 180px; height: 180px;
  background: #00e08a;
  bottom: -50px; right: -40px;
  animation: gen-drift-b 11s ease-in-out infinite alternate;
}
@keyframes gen-drift-a {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(40px, 30px) scale(1.15); }
}
@keyframes gen-drift-b {
  from { transform: translate(0, 0) scale(1.1); }
  to   { transform: translate(-35px, -25px) scale(0.95); }
}

.gen-dot {
  width: 7px; height: 7px;
  border-radius: 9999px;
  background: currentColor;
  opacity: 0.25;
  flex-shrink: 0;
  transition: opacity 0.3s, transform 0.3s;
}
/* Current stage: pulsing. Completed stages: solid and full opacity. */
.gen-step.is-active { color: var(--color-primary, #0052cc); font-weight: 600; }
.gen-step.is-active .gen-dot { opacity: 1; animation: gen-pulse 1.2s ease-in-out infinite; }
.gen-step.is-done { color: var(--color-primary, #0052cc); }
.gen-step.is-done .gen-dot { opacity: 1; transform: scale(1.15); }
@keyframes gen-pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(1.6); opacity: 0.5; }
}

@media (prefers-reduced-motion: reduce) {
  .gen-orb, .gen-step.is-active .gen-dot { animation: none; }
}

/* ---------------------------------------------------------------------------
   Mobile bottom navigation
   The old icons were 18px grey glyphs with 8px labels: hard to hit and hard to
   tell which tab was active. Bigger glyphs, a real active pill, and a colour
   change so the current tab is obvious at a glance.
--------------------------------------------------------------------------- */
.mob-nav-item {
  color: #6b7280;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.mob-nav-item .material-symbols-outlined {
  transition: transform 0.18s ease, color 0.18s ease;
}
.mob-nav-item:active .material-symbols-outlined {
  transform: scale(0.88);
}
.mob-nav-item.active {
  color: var(--color-primary, #0052cc);
  background: rgba(0, 82, 204, 0.10);
  font-weight: 700;
}
.mob-nav-item.active .material-symbols-outlined {
  font-variation-settings: 'FILL' 1;
  transform: translateY(-1px) scale(1.06);
}
/* Small dot under the active tab, the standard mobile affordance. */
.mob-nav-item.active::after {
  content: '';
  position: absolute;
  bottom: -2px;
  width: 5px;
  height: 5px;
  border-radius: 9999px;
  background: var(--color-primary, #0052cc);
}
.dark .mob-nav-item { color: #9ca3af; }
.dark .mob-nav-item.active {
  color: #7aa7ff;
  background: rgba(122, 167, 255, 0.16);
}
.dark .mob-nav-item.active::after { background: #7aa7ff; }

@media (prefers-reduced-motion: reduce) {
  .mob-nav-item .material-symbols-outlined { transition: none; }
}

/* ===========================================================================
   Result media presentation
   Generated work is the product, so it should be framed like it. Deep rounded
   corners, layered shadows, a gradient scrim so overlaid text stays readable
   on any image, and a controlled hover lift.
   =========================================================================== */

.media-card {
  position: relative;
  border-radius: 1.25rem;
  overflow: hidden;
  background: #0b0f17;
  box-shadow:
    0 1px 2px rgba(16, 24, 40, 0.06),
    0 8px 24px -8px rgba(16, 24, 40, 0.18);
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.28s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.media-card:hover {
  transform: translateY(-4px);
  box-shadow:
    0 2px 4px rgba(16, 24, 40, 0.08),
    0 20px 40px -12px rgba(0, 61, 155, 0.30);
}
.media-card img,
.media-card video,
.media-card canvas {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.media-card:hover img,
.media-card:hover video {
  transform: scale(1.04);
}

/* Readable overlay text regardless of what the model produced underneath. */
.media-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(6, 10, 18, 0.88) 0%,
    rgba(6, 10, 18, 0.45) 32%,
    rgba(6, 10, 18, 0) 62%
  );
  pointer-events: none;
}

/* Action buttons that sit on top of media. */
.media-action {
  backdrop-filter: blur(10px);
  background: rgba(255, 255, 255, 0.90);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  transition: transform 0.18s ease, background 0.18s ease;
}
.media-action:hover { transform: scale(1.08); background: #fff; }
.media-action:active { transform: scale(0.94); }

/* Shimmer while a result is still rendering, instead of a dead grey box. */
.media-skeleton {
  background: linear-gradient(100deg,
    var(--sk-a, #eceff3) 20%,
    var(--sk-b, #f6f8fa) 40%,
    var(--sk-a, #eceff3) 60%);
  background-size: 220% 100%;
  animation: media-shimmer 1.5s linear infinite;
}
@keyframes media-shimmer {
  from { background-position: 180% 0; }
  to   { background-position: -60% 0; }
}
.dark .media-skeleton { --sk-a: #1b2130; --sk-b: #262e40; }

/* ---------------------------------------------------------------------------
   Icons
   Material Symbols default to a thin 400 weight that looks washed out at small
   sizes. Nudging weight and optical size makes them read as deliberate.
--------------------------------------------------------------------------- */
.material-symbols-outlined {
  font-variation-settings: 'FILL' 0, 'wght' 500, 'GRAD' 0, 'opsz' 24;
}
.icon-fill {
  font-variation-settings: 'FILL' 1, 'wght' 500, 'GRAD' 0, 'opsz' 24;
}
/* Icons inside a coloured chip or button carry more weight. */
button .material-symbols-outlined,
.nav-link .material-symbols-outlined,
.mob-nav-item .material-symbols-outlined {
  font-variation-settings: 'FILL' 0, 'wght' 600, 'GRAD' 0, 'opsz' 24;
}
button .icon-fill,
.nav-link.active .material-symbols-outlined,
.mob-nav-item.active .material-symbols-outlined {
  font-variation-settings: 'FILL' 1, 'wght' 600, 'GRAD' 0, 'opsz' 24;
}

/* Studio section icons: circular gradient badge rather than a bare glyph. */
.icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.875rem;
  background: linear-gradient(135deg, #0052cc 0%, #003d9b 100%);
  color: #fff;
  box-shadow: 0 6px 16px -6px rgba(0, 82, 204, 0.55);
  flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
  .media-card, .media-card img, .media-card video, .media-action { transition: none; }
  .media-card:hover { transform: none; }
  .media-card:hover img, .media-card:hover video { transform: none; }
  .media-skeleton { animation: none; }
}

/* ---------------------------------------------------------------------------
   Studio hero banners
   Each studio leads with a photo of the work it produces. The scrim is a hard
   requirement, not decoration: headings sit directly on the photo, and without
   a guaranteed dark base the text fails contrast over the lighter areas.
   --------------------------------------------------------------------------- */
.studio-hero {
  position: relative;
  border-radius: 1rem;
  overflow: hidden;
  background-color: #001233;
  background-image: var(--studio-img);
  background-size: cover;
  background-position: center;
  isolation: isolate;
}

.studio-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(100deg, rgba(0, 18, 51, 0.94) 0%, rgba(0, 18, 51, 0.82) 42%, rgba(0, 40, 120, 0.45) 72%, rgba(0, 40, 120, 0.15) 100%);
}

.studio-hero-inner {
  position: relative;
  z-index: 1;
  padding: 1.5rem 1.25rem;
  max-width: 46rem;
}

@media (min-width: 768px) {
  .studio-hero-inner { padding: 2.25rem 2rem; }
}

/* On narrow screens the photo has little room to read, so lean darker and keep
   the copy legible rather than showing more of the image. */
@media (max-width: 767px) {
  .studio-hero::after {
    background: linear-gradient(160deg, rgba(0, 18, 51, 0.92) 0%, rgba(0, 18, 51, 0.86) 55%, rgba(0, 40, 120, 0.62) 100%);
  }
}

/* ---------------------------------------------------------------------------
   Levitating decor + glitter
   Floating artwork drifts on its own behind the content. Everything here is
   decorative, sits behind the copy, and is disabled for anyone who has asked
   their system to reduce motion.
   --------------------------------------------------------------------------- */
.levitate {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  border-radius: 1rem;
  overflow: hidden;
  box-shadow: 0 18px 40px -12px rgba(0, 10, 40, 0.6);
  border: 1.5px solid rgba(125, 211, 252, 0.45);
  will-change: transform;
}

.levitate img { width: 100%; height: 100%; object-fit: cover; display: block; }

@keyframes levitateA {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-3deg); }
  50%      { transform: translate3d(0, -22px, 0) rotate(-1deg); }
}
@keyframes levitateB {
  0%, 100% { transform: translate3d(0, -10px, 0) rotate(4deg); }
  50%      { transform: translate3d(0, 14px, 0) rotate(1.5deg); }
}
@keyframes levitateC {
  0%, 100% { transform: translate3d(0, 6px, 0) rotate(-6deg) scale(1); }
  50%      { transform: translate3d(0, -16px, 0) rotate(-2deg) scale(1.04); }
}

.levitate-a { animation: levitateA 7s ease-in-out infinite; }
.levitate-a, .levitate-b, .levitate-c { will-change: transform; backface-visibility: hidden; }
.levitate-b { animation: levitateB 9s ease-in-out infinite; }
.levitate-c { animation: levitateC 11s ease-in-out infinite; }

/* Drifting light particles over a section. Uses the grain/particles plate. */
.glitter::before {
  content: '';
  position: absolute;
  inset: -20%;
  z-index: 0;
  pointer-events: none;
  background-image: url('/assets/img/22-grain-light-particles-overlay.webp');
  background-size: cover;
  /* mix-blend-mode: screen was the main cause of scroll stutter. Blending
     defeats layer isolation, so the browser had to re-composite the whole
     stacking context behind ELEVEN of these on every animation frame. Plain
     opacity looks near-identical for a light particle plate and composites
     on the GPU. */
  opacity: 0.22;
  will-change: transform;
  animation: glitterDrift 26s linear infinite;
}

/* Keep the drifting layer from forcing layout/paint work outside its own box. */
.glitter { contain: paint; }

/* Phones do the least work: the texture stays, the motion stops. Continuous
   full-bleed animation is where mid-range devices lose frames. */
@media (max-width: 767px) {
  .glitter::before { animation: none; opacity: 0.16; }
  .accent-icon { animation: none !important; }
}

@keyframes glitterDrift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-3%, -2%, 0) scale(1.06); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

/* A slow sheen that travels across a heading. */
.shimmer {
  background-size: 200% auto;
  animation: shimmerSweep 6s linear infinite;
}

@keyframes shimmerSweep {
  to { background-position: 200% center; }
}

/* Small glowing accent icon, used beside studio headings. */
.accent-icon {
  width: 2.5rem;
  height: 2.5rem;
  object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(56, 189, 248, 0.75));
}

@media (prefers-reduced-motion: reduce) {
  .levitate-a, .levitate-b, .levitate-c,
  .glitter::before, .shimmer { animation: none !important; }
}

/* The floating pieces are scenery, not content - below the phone breakpoint
   they would sit under the copy and fight it, so they come out entirely. */
@media (max-width: 767px) {
  .levitate { display: none; }
}

/* Soft cyan bloom, layered over a panel's own background. */
.glow-cyan { position: relative; isolation: isolate; }
.glow-cyan::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('/assets/img/19-soft-cyan-glow-overlay.webp') center / cover no-repeat;
  /* Same reasoning as .glitter: blending forces the browser out of cheap GPU
     compositing. Plain opacity reads the same over a dark hero. */
  opacity: 0.32;
}

/* Ribbon sweep for light panels; multiply keeps it from washing the panel out. */
.ribbon-blue { position: relative; isolation: isolate; }
.ribbon-blue::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('/assets/img/20-royal-blue-ribbon-overlay.webp') center / cover no-repeat;
  opacity: 0.16;
}
.ribbon-blue > * { position: relative; z-index: 1; }

/* ---------------------------------------------------------------------------
   Poster carousel
   Horizontal scroll-snap rather than a transform track: swipe, trackpad and
   keyboard all work natively, and it degrades to a plain scroller if the
   script never runs.
   --------------------------------------------------------------------------- */
.carousel {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.25rem;
}
.carousel::-webkit-scrollbar { display: none; }

.carousel-slide {
  flex: 0 0 auto;
  width: 72%;
  max-width: 300px;
  scroll-snap-align: center;
  border-radius: 1rem;
  overflow: hidden;
  border: 1.5px solid rgba(125, 211, 252, 0.35);
  box-shadow: 0 14px 34px -14px rgba(0, 20, 60, 0.55);
  background: #001233;
  transition: transform 0.35s ease, box-shadow 0.35s ease;
}
@media (min-width: 768px) { .carousel-slide { width: 30%; max-width: 320px; } }

.carousel-slide img { width: 100%; height: 100%; object-fit: cover; display: block; }
.carousel-slide.is-active { transform: translateY(-6px) scale(1.02); box-shadow: 0 22px 44px -14px rgba(0, 40, 140, 0.6); }

.carousel-btn {
  width: 2.5rem; height: 2.5rem;
  display: grid; place-items: center;
  border-radius: 9999px;
  background: var(--carousel-btn-bg, #ffffff);
  color: #003d9b;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 4px 14px -4px rgba(0, 20, 60, 0.35);
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.carousel-btn:hover { transform: scale(1.08); }
.carousel-btn:disabled { opacity: 0.35; cursor: default; transform: none; }

.carousel-dot {
  width: 7px; height: 7px; border-radius: 9999px;
  background: rgba(0, 61, 155, 0.25);
  transition: width 0.25s ease, background 0.25s ease;
}
.carousel-dot.is-active { width: 22px; background: #003d9b; }

@media (prefers-reduced-motion: reduce) {
  .carousel { scroll-behavior: auto; }
  .carousel-slide, .carousel-btn { transition: none; }
}

/* Studio hero, two-column on desktop: the photo becomes a real visible card
   beside the copy instead of a dark plate behind it. Below md it stays a
   background, because side-by-side has nowhere to go on a phone. */
@media (min-width: 768px) {
  .studio-hero.has-visual .studio-hero-inner {
    display: flex;
    align-items: center;
    gap: 2rem;
    max-width: none;
  }
  .studio-hero.has-visual .studio-hero-copy { flex: 1 1 auto; max-width: 34rem; }
  .studio-hero.has-visual .studio-hero-visual {
    flex: 0 0 auto;
    width: 15rem;
    border-radius: 0.9rem;
    overflow: hidden;
    border: 1.5px solid rgba(125, 211, 252, 0.5);
    box-shadow: 0 18px 40px -14px rgba(0, 10, 40, 0.65);
  }
  .studio-hero.has-visual .studio-hero-visual img {
    width: 100%; height: 100%; object-fit: cover; display: block;
  }
  /* With the photo shown properly beside the text, the scrim no longer has to
     hide it - lighten so the backdrop reads too. */
  .studio-hero.has-visual::after {
    background: linear-gradient(100deg, rgba(0,18,51,0.90) 0%, rgba(0,18,51,0.74) 45%, rgba(0,30,90,0.5) 100%);
  }
}
.studio-hero-visual { display: none; }
@media (min-width: 768px) { .studio-hero.has-visual .studio-hero-visual { display: block; } }

/* Gradient-clipped text cannot take a text-shadow (the fill is transparent),
   so the lift has to come from a filter on the element itself. */
.hero-accent {
  filter: drop-shadow(0 1px 2px rgba(0, 8, 24, 0.95)) drop-shadow(0 3px 14px rgba(0, 8, 24, 0.8));
}

@media (max-width: 767px) {
  .creative-hero-bg {
    background:
      linear-gradient(165deg, rgba(0, 14, 40, 0.88) 0%, rgba(0, 14, 40, 0.8) 55%, rgba(0, 30, 90, 0.62) 100%),
      url('/assets/img/01-hero-collage.webp') center / cover no-repeat,
      linear-gradient(135deg, #001233 0%, #002878 35%, #0052cc 70%, #0077ff 100%);
  }
}


/* ---------------------------------------------------------------------------
   Dark mode: bind Tailwind's surface utilities to the theme variables

   styles.css already defines a full dark palette in the .dark block above, but
   the Tailwind config in index.html hardcodes the LIGHT hex for every token
   ("surface": "#f9f9f9"), so its generated utilities never read those
   variables — `.bg-surface` paints #f9f9f9 even in dark mode, and
   `dark:bg-surface-container-high` paints #e8e8e8, a light grey.

   These rules point the utilities back at the variables, so the .dark block
   stays the single source of truth. !important is needed because Tailwind's
   runtime stylesheet is injected after this file and its `:is(.dark *)`
   variants carry equal-or-higher specificity.
   --------------------------------------------------------------------------- */
html.dark,
html.dark body,
html.dark .bg-surface,
html.dark .bg-background,
html.dark .dark\:bg-on-background          { background-color: #0f131a !important; }

html.dark .bg-surface-container-lowest,
html.dark .dark\:bg-surface-container-lowest { background-color: var(--color-surface-container-lowest) !important; }

html.dark .bg-surface-container-low,
html.dark .dark\:bg-surface-container-low    { background-color: var(--color-surface-container-low) !important; }

html.dark .bg-surface-container,
html.dark .dark\:bg-surface-container        { background-color: var(--color-surface-container) !important; }

html.dark .bg-surface-container-high,
html.dark .dark\:bg-surface-container-high   { background-color: var(--color-surface-container-high) !important; }

html.dark .bg-surface-container-highest,
html.dark .dark\:bg-surface-container-highest{ background-color: var(--color-surface-container-highest) !important; }

html.dark .bg-white                          { background-color: var(--color-surface-container-lowest) !important; }

/* Text and borders authored against light surfaces. */
html.dark .text-on-surface,
html.dark .text-on-background   { color: var(--color-on-surface) !important; }
html.dark .text-secondary       { color: var(--color-secondary) !important; }
html.dark .text-primary         { color: var(--color-primary) !important; }
html.dark .border-slate-border      { border-color: var(--color-slate-border) !important; }
html.dark .border-slate-border\/60 { border-color: color-mix(in srgb, var(--color-slate-border) 60%, transparent) !important; }
html.dark .border-slate-border\/50 { border-color: color-mix(in srgb, var(--color-slate-border) 50%, transparent) !important; }
html.dark .border-slate-border\/40 { border-color: color-mix(in srgb, var(--color-slate-border) 40%, transparent) !important; }

/* The idea-to-video CTA holds a white-background illustration, so that one
   panel stays light on purpose and keeps its own hardcoded dark text. */
html.dark .bg-\[\#f4f7ff\]   { background-color: #e9edfb !important; }

/* ---------------------------------------------------------------------------
   Dark mode, final pass — literal values, one selector per rule.

   The var()-based rules above work for most elements but silently failed on
   body and the header. Rather than keep chasing why, these use literal hex and
   single simple selectors: no custom-property resolution to go wrong, and no
   comma-separated list that a single bad selector could invalidate.
   --------------------------------------------------------------------------- */
html.dark body                       { background-color: #0f131a !important; color: #f0f2f8 !important; }
html.dark header                     { background-color: #0f131a !important; }
html.dark aside                      { background-color: #151a24 !important; }
html.dark main                       { color: #f0f2f8 !important; }
html.dark details                    { color: #f0f2f8 !important; }
html.dark summary                    { color: #f0f2f8 !important; }
html.dark nav                        { background-color: transparent; }

/* The mobile bottom bar sits on its own surface. */
html.dark .mob-nav-bar,
html.dark [class*="mob-nav"]         { color: #cbd5e1; }

/* Headings and body copy that inherited a light-theme colour. */
html.dark h1, html.dark h2, html.dark h3, html.dark h4 { color: #f0f2f8; }
html.dark p, html.dark li, html.dark label             { color: #cbd5e1; }

/* Anything explicitly painted white must stay dark-safe. */
html.dark .text-white                { color: #ffffff !important; }

/* Panels deliberately kept light keep their own dark text. */
html.dark .bg-\[\#f4f7ff\],
html.dark .bg-\[\#f4f7ff\] h1,
html.dark .bg-\[\#f4f7ff\] h2,
html.dark .bg-\[\#f4f7ff\] h3,
html.dark .bg-\[\#f4f7ff\] p         { color: #1a1c1c !important; }
html.dark .bg-\[\#f4f7ff\]           { background-color: #e9edfb !important; }

/* Studio heroes and the hero banner carry their own photo + scrim; their copy
   is authored white and must not be repainted by the rules above. */
html.dark .studio-hero h1, html.dark .studio-hero h2, html.dark .studio-hero h3,
html.dark .studio-hero p,
html.dark .creative-hero-bg h1, html.dark .creative-hero-bg p { color: #ffffff; }

/* Missed on the first pass: primary-container (#0052cc) as a TEXT colour is
   also a dark navy and drops to 1.86:1 on dark panels. */
html.dark .text-primary-container,
html.dark .text-on-primary-container { color: #8ab4ff !important; }

/* ===========================================================================
   Calm redesign (September 2026)
   The home hero and studio headers had five competing layers: a collage photo
   behind the text, floating cards, a drifting particle plate, spinning icons
   and heavy text shadows. Everything below replaces that with still, solid
   panels. The older rules above are left in place but no longer match.
   =========================================================================== */

/* ---- Home hero ---------------------------------------------------------- */
.hero-calm {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: 2rem;
  padding: 2rem 1.5rem;
  border-radius: 1.5rem;
  background: #003d9b;
  color: #ffffff;
}
@media (min-width: 768px) {
  .hero-calm { grid-template-columns: minmax(0, 1fr) 15rem; padding: 3rem; gap: 3rem; }
}
@media (min-width: 1280px) {
  .hero-calm { grid-template-columns: minmax(0, 1fr) 18rem; padding: 3.5rem 4rem; }
}

.hero-calm .hero-calm-title {
  margin: 0 0 0.9rem;
  max-width: 15ch;
  font-size: clamp(2rem, 1.35rem + 2.4vw, 3.25rem);
  line-height: 1.08;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #ffffff;
  text-shadow: none;
}
.hero-calm .hero-calm-sub {
  margin: 0 0 1.75rem;
  max-width: 34ch;
  font-size: 1.0625rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.8);
  text-shadow: none;
}
.hero-calm-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
}
.hero-calm .hero-calm-cta {
  background: #ffffff;
  color: #003d9b;
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.85rem 1.5rem;
  border-radius: 0.85rem;
  transition: background-color 0.15s ease;
}
.hero-calm .hero-calm-cta:hover { background: #e6edff; }
.hero-calm .hero-calm-link {
  color: #ffffff;
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(255, 255, 255, 0.45);
}
.hero-calm .hero-calm-link:hover { text-decoration-color: #ffffff; }
.hero-calm .hero-calm-cta:focus-visible,
.hero-calm .hero-calm-link:focus-visible,
.hero-calm .hero-calm-play:focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }

/* The real piece of work sits beside the copy, never behind it. Phones skip it
   so the first screen shows the promise and the button, then real designs. */
.hero-calm-visual { display: none; margin: 0; }
@media (min-width: 768px) { .hero-calm-visual { display: block; } }
.hero-calm-play {
  position: relative;
  display: block;
  width: 100%;
  border-radius: 1rem;
  overflow: hidden;
  background: #001a4d;
}
.hero-calm-play img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.hero-calm-play-badge {
  position: absolute;
  left: 0.75rem;
  bottom: 0.75rem;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 9999px;
  background: #ffffff;
  color: #003d9b;
}
.hero-calm-visual figcaption {
  margin-top: 0.6rem;
  font-size: 0.75rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.72);
}

/* Dark mode keeps the same panel. The catch-all dark rules for white
   backgrounds and body text must not reach into it. */
html.dark .hero-calm { background: #0a3a8c; }
html.dark .hero-calm .hero-calm-cta { background: #ffffff !important; color: #003d9b !important; }
html.dark .hero-calm .hero-calm-sub,
html.dark .hero-calm figcaption { color: rgba(255, 255, 255, 0.8); }

/* ---- Studio headers: the tool comes first ------------------------------- */
.studio-hero {
  background-image: none !important;
  background-color: #003d9b;
  border-radius: 1rem;
}
.studio-hero::after { display: none; }
.studio-hero .accent-icon,
.studio-hero .studio-hero-visual { display: none !important; }
.studio-hero .studio-hero-inner,
.studio-hero.has-visual .studio-hero-inner {
  display: block;
  max-width: none;
  padding: 1rem 1.25rem;
}
@media (min-width: 768px) {
  .studio-hero .studio-hero-inner,
  .studio-hero.has-visual .studio-hero-inner { padding: 1.25rem 1.75rem; }
}
.studio-hero h1,
.studio-hero h2 {
  margin: 0 0 0.25rem;
  font-size: 1.35rem !important;
  line-height: 1.25 !important;
  text-shadow: none !important;
}
.studio-hero p {
  margin: 0;
  font-size: 0.9rem !important;
  line-height: 1.45 !important;
  color: rgba(255, 255, 255, 0.8) !important;
  text-shadow: none !important;
}
html.dark .studio-hero { background-color: #0a3a8c; }

/* ---- Site-wide: no drifting or floating decoration ----------------------- */
.glitter::before,
.glow-cyan::before { content: none !important; animation: none !important; }
.levitate { display: none !important; }
.levitate-a, .levitate-b, .levitate-c,
.levitate-card-1, .levitate-card-2, .levitate-card-3, .levitate-card-4,
.shimmer { animation: none !important; }

/* ---- Speaking-video studios (UGC, Product & CEO) ------------------------
   One column, one decision per row, no side gallery. Plain CSS rather than
   utility classes so the look survives without a Tailwind rebuild. */
.studio-form {
  max-width: 40rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.5rem;
  border-radius: 1rem;
  border: 1px solid #e4e7ec;
  background: #ffffff;
}
@media (min-width: 768px) { .studio-form { padding: 2rem; } }

.studio-field { display: flex; flex-direction: column; gap: 0.5rem; }
.studio-label { font-size: 0.875rem; font-weight: 700; color: #1a1c1c; margin: 0; }
.studio-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.studio-link { font-size: 0.8125rem; font-weight: 600; color: #003d9b; text-decoration: underline; text-underline-offset: 3px; }
.studio-hint { font-size: 0.8125rem; line-height: 1.45; color: #555f6c; margin: 0; }
.studio-hint.is-warning { color: #b45309; font-weight: 600; }

.studio-input {
  width: 100%;
  padding: 0.75rem 0.875rem;
  border-radius: 0.75rem;
  border: 1px solid #d0d5dd;
  background: #ffffff;
  color: #1a1c1c;
  font-size: 0.9375rem;
  line-height: 1.5;
}
.studio-input:focus { outline: 2px solid #003d9b; outline-offset: 1px; border-color: #003d9b; }
.studio-textarea { resize: vertical; min-height: 5.5rem; }

.chip-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip {
  padding: 0.5rem 0.9rem;
  border-radius: 9999px;
  border: 1px solid #d0d5dd;
  background: #ffffff;
  color: #434654;
  font-size: 0.8125rem;
  font-weight: 600;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.chip:hover { border-color: #003d9b; }
.chip[aria-pressed="true"] { background: #003d9b; border-color: #003d9b; color: #ffffff; }
.chip:focus-visible { outline: 2px solid #003d9b; outline-offset: 2px; }

.studio-generate {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.95rem 1rem;
  border-radius: 0.85rem;
  background: #003d9b;
  color: #ffffff;
  font-size: 1rem;
  font-weight: 700;
  transition: background-color 0.15s ease;
}
.studio-generate:hover { background: #0052cc; }
.studio-generate:disabled { opacity: 0.6; cursor: progress; }
.studio-cost { font-weight: 500; opacity: 0.8; }
.studio-cost:not(:empty)::before { content: '· '; }

html.dark .studio-form { background: #161b24; border-color: #2a3140; }
html.dark .studio-label { color: #f0f2f8; }
html.dark .studio-hint { color: #aab4c4; }
html.dark .studio-hint.is-warning { color: #fbbf24; }
html.dark .studio-link { color: #8ab4ff; }
html.dark .studio-input { background: #0f131a; border-color: #2f3746; color: #f0f2f8; }
html.dark .studio-input:focus { outline-color: #8ab4ff; border-color: #8ab4ff; }
html.dark .chip { background: #0f131a; border-color: #2f3746; color: #cbd5e1; }
html.dark .chip:hover { border-color: #8ab4ff; }
html.dark .chip[aria-pressed="true"] { background: #2563eb; border-color: #2563eb; color: #ffffff; }
html.dark .studio-generate { background: #2563eb; }
html.dark .studio-generate:hover { background: #3b82f6; }

/* ---- Star in it: photo picker and own-voice recorder --------------------- */
.face-preview[hidden], .voice-box[hidden], .face-add[hidden], audio[hidden] { display: none !important; }
.studio-optional { font-weight: 500; color: #6b7280; }

.face-add {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.85rem 1rem;
  border-radius: 0.75rem;
  border: 1.5px dashed #c3c6d6;
  background: transparent;
  color: #434654;
  font-size: 0.875rem;
  font-weight: 600;
  text-align: left;
}
.face-add:hover { border-color: #003d9b; color: #003d9b; }
.face-preview { display: flex; align-items: center; gap: 0.85rem; }
.face-preview img { width: 3.5rem; height: 3.5rem; border-radius: 0.75rem; object-fit: cover; background: #eef1f6; }
.face-status { flex: 1; font-size: 0.875rem; font-weight: 600; color: #1a1c1c; }

.voice-box {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 0.75rem;
  padding: 0.9rem;
  border-radius: 0.75rem;
  border: 1px solid #e4e7ec;
  background: #f7f8fb;
}
.voice-row { display: flex; align-items: center; gap: 0.75rem; }
.voice-rec {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 9999px;
  background: #ba1a1a;
  color: #ffffff;
}
.voice-rec.is-recording { background: #1a1c1c; }
.voice-rec:disabled { opacity: 0.5; }
.voice-meta { flex: 1; min-width: 0; }
.voice-status { margin: 0; font-size: 0.875rem; font-weight: 600; color: #1a1c1c; }
.voice-meter { height: 0.35rem; margin-top: 0.4rem; border-radius: 9999px; background: #e4e7ec; overflow: hidden; }
.voice-meter > div { width: 0; height: 100%; background: #003d9b; transition: width 80ms linear; }
.voice-timer { font-size: 0.8125rem; color: #555f6c; font-variant-numeric: tabular-nums; }
.voice-box audio { width: 100%; height: 2.25rem; }

html.dark .studio-optional { color: #9aa3b2; }
html.dark .face-add { border-color: #3a4252; color: #cbd5e1; }
html.dark .face-add:hover { border-color: #8ab4ff; color: #8ab4ff; }
html.dark .face-status, html.dark .voice-status { color: #f0f2f8; }
html.dark .voice-box { background: #0f131a; border-color: #2f3746; }
html.dark .voice-meter { background: #2a3140; }
html.dark .voice-meter > div { background: #8ab4ff; }
html.dark .voice-timer { color: #aab4c4; }

/* ---- Microphone dictation on prompt boxes ------------------------------- */
.dictate-wrap { position: relative; display: block; }
.dictate-wrap > textarea { padding-right: 3rem !important; }
.dictate-btn {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 9999px;
  background: #eef2fb;
  color: #003d9b;
  border: 1px solid #d6def0;
}
.dictate-btn:hover { background: #dfe7fa; }
.dictate-btn.is-listening { background: #ba1a1a; border-color: #ba1a1a; color: #ffffff; animation: dictatePulse 1.4s ease-in-out infinite; }
.dictate-btn.is-working { opacity: 0.6; cursor: progress; }
.dictate-btn .material-symbols-outlined { font-size: 1.25rem; }
@keyframes dictatePulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(186, 26, 26, 0.45); } 50% { box-shadow: 0 0 0 6px rgba(186, 26, 26, 0); } }
@media (prefers-reduced-motion: reduce) { .dictate-btn.is-listening { animation: none; } }
html.dark .dictate-btn { background: #1c2433; border-color: #2f3746; color: #8ab4ff; }
html.dark .dictate-btn:hover { background: #243048; }

/* ---- Video viewer close button (always reachable on phones) -------------- */
.modal-close-top {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 20;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 9999px;
  background: rgba(0, 0, 0, 0.6);
  color: #ffffff;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.modal-close-top:hover { background: rgba(0, 0, 0, 0.8); }
.modal-close-top:focus-visible { outline: 2px solid #ffffff; outline-offset: 2px; }
.modal-close-top .material-symbols-outlined { font-size: 1.6rem; }

/* ---- Logo and product images in the speaking studios -------------------- */
.asset-buttons { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.asset-add {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 10rem;
  justify-content: center;
  padding: 0.7rem 0.9rem;
  border-radius: 0.75rem;
  border: 1.5px dashed #c3c6d6;
  color: #434654;
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}
.asset-add:hover, .asset-add:focus-within { border-color: #003d9b; color: #003d9b; }
.asset-add .material-symbols-outlined { font-size: 1.15rem; }
html.dark .asset-add { border-color: #3a4356; color: #cbd5e1; }
html.dark .asset-add:hover, html.dark .asset-add:focus-within { border-color: #8ab4ff; color: #8ab4ff; }

/* ---- Continue the story ------------------------------------------------- */
.continue-banner {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1rem;
  padding: 0.75rem;
  border-radius: 0.875rem;
  border: 1px solid #b7c8ec;
  background: #eef3fd;
}
.continue-banner[hidden] { display: none !important; }
#continue-thumb {
  flex: 0 0 auto;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 0.6rem;
  object-fit: cover;
  background: #dfe5f1;
}
.continue-copy { flex: 1; min-width: 0; }
.continue-kicker { margin: 0; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #003d9b; }
.continue-title { margin: 0.15rem 0 0; font-size: 0.875rem; font-weight: 700; color: #1a1c1c; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.continue-status { margin: 0.15rem 0 0; font-size: 0.75rem; line-height: 1.4; color: #555f6c; }
html.dark .continue-banner { background: #141c2c; border-color: #2c3b5a; }
html.dark #continue-thumb { background: #1f2738; }
html.dark .continue-kicker { color: #8ab4ff; }
html.dark .continue-title { color: #f0f2f8; }
html.dark .continue-status { color: #aab4c4; }

.video-qty { margin-bottom: 1rem; }

.modal-continue-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  margin-bottom: 0.6rem;
  padding: 0.8rem 1rem;
  border-radius: 0.75rem;
  border: 1.5px solid #003d9b;
  background: transparent;
  color: #003d9b;
  font-size: 0.875rem;
  font-weight: 700;
}
.modal-continue-btn[hidden] { display: none !important; }
.modal-continue-btn:hover { background: rgba(0, 61, 155, 0.08); }
html.dark .modal-continue-btn { border-color: #8ab4ff; color: #8ab4ff; }
html.dark .modal-continue-btn:hover { background: rgba(138, 180, 255, 0.1); }

/* ---- Inline generation cards --------------------------------------------
   A small box under each Generate button. It paints itself while the video
   renders, then the finished video plays inside the same box. Plain CSS so it
   needs no Tailwind rebuild. */
.gen-cards { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem; }
.gen-cards[hidden] { display: none !important; }
#story-gen-cards { margin-top: 1rem; }

.gen-card {
  --gen-ar: 9 / 16;
  flex: 0 0 auto;
  width: 240px;
  max-width: 100%;
  border-radius: 1rem;
  border: 1px solid #e4e7ec;
  background: #ffffff;
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06);
  animation: genCardIn 0.35s ease-out both;
}
.gen-card[data-ratio="9:16"] { width: 216px; }
.gen-card[data-ratio="16:9"] { width: 280px; }
.gen-card.is-loading { animation: genCardIn 0.35s ease-out both, genGlow 2.8s ease-in-out 0.35s infinite; }

.gen-card-frame {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: var(--gen-ar);
  max-height: 384px;
  overflow: hidden;
  background: #eef2fb;
}

/* The "being painted" surface: a slow colour wash, two soft drifting lights
   and a gentle sheen passing over. */
.gen-card-paint {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #dbe6ff 0%, #ece3ff 35%, #d8f0ff 65%, #dbe6ff 100%);
  background-size: 300% 300%;
  animation: genPaint 9s ease-in-out infinite;
}
.gen-card-blob {
  position: absolute;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 9999px;
  filter: blur(22px);
  opacity: 0.55;
}
.gen-card-blob-a { top: -15%; left: -20%; background: #7aa2ff; animation: genDriftA 7s ease-in-out infinite; }
.gen-card-blob-b { bottom: -20%; right: -25%; background: #b794f6; animation: genDriftB 8.5s ease-in-out infinite; }
.gen-card-sweep {
  position: absolute;
  inset: -50% -100%;
  background: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, 0.55) 50%, transparent 58%);
  animation: genSweep 2.6s ease-in-out infinite;
}
.gen-card-line {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0 0.9rem;
  max-width: 100%;
  text-align: center;
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.35;
  color: #102a5c;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.gen-card-line.is-out { opacity: 0; transform: translateY(4px); }

.gen-card-body { padding: 0.65rem 0.75rem 0.75rem; }
.gen-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; }
.gen-card-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.8125rem; font-weight: 700; color: #1a1c1c; }
.gen-card-time { flex: 0 0 auto; font-size: 0.75rem; color: #555f6c; font-variant-numeric: tabular-nums; }
.gen-card-bar { height: 4px; margin-top: 0.5rem; border-radius: 9999px; background: #e4e7ec; overflow: hidden; }
.gen-card-bar > span { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #003d9b, #6d28d9); transition: width 0.9s ease; }
.gen-card-status { margin: 0.45rem 0 0; font-size: 0.75rem; line-height: 1.4; color: #555f6c; }

.gen-card-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; }
.gen-card-actions[hidden] { display: none !important; }
.gen-card-action {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4rem 0.65rem;
  border-radius: 9999px;
  border: 1px solid #d0d5dd;
  background: #ffffff;
  color: #003d9b;
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
}
.gen-card-action:hover { border-color: #003d9b; background: #f2f6fe; }
.gen-card-action:focus-visible { outline: 2px solid #003d9b; outline-offset: 2px; }
.gen-card-action:disabled { opacity: 0.6; cursor: progress; }
.gen-card-action .material-symbols-outlined { font-size: 1rem; }

.gen-card.is-done .gen-card-frame { background: #000000; }
.gen-card-video { display: block; width: 100%; height: 100%; object-fit: contain; background: #000000; }

.gen-card.is-failed .gen-card-frame { background: #fdf3f3; }
.gen-card.is-failed .gen-card-bar > span { background: #ba1a1a; }
.gen-card-error { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; padding: 1rem; text-align: center; }
.gen-card-error .material-symbols-outlined { font-size: 1.75rem; color: #ba1a1a; }
.gen-card-error p { margin: 0; font-size: 0.875rem; font-weight: 700; line-height: 1.4; color: #1a1c1c; }
.gen-card.is-failed .gen-card-status { overflow-wrap: anywhere; }

/* Phones: wide and square boxes take the width (up to 320px); tall ones sit
   two to a row when there are several, so the page stays short. */
@media (max-width: 639px) {
  .gen-card, .gen-card[data-ratio="16:9"] { width: 100%; max-width: 320px; }
  .gen-card[data-ratio="9:16"] { flex: 1 1 130px; width: auto; max-width: 216px; }
}

@keyframes genCardIn { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
@keyframes genGlow { 0%, 100% { box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06), 0 0 0 0 rgba(37, 99, 235, 0); } 50% { box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06), 0 0 0 4px rgba(37, 99, 235, 0.18); } }
@keyframes genPaint { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@keyframes genDriftA { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(35%, 25%); } }
@keyframes genDriftB { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-30%, -30%); } }
@keyframes genSweep { 0% { transform: translateX(-35%); } 100% { transform: translateX(35%); } }

html.dark .gen-card { background: #161b24; border-color: #2a3140; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35); }
html.dark .gen-card-frame { background: #0f1630; }
html.dark .gen-card-paint { background-image: linear-gradient(135deg, #10204a 0%, #2a1a52 35%, #0b2f4a 65%, #10204a 100%); }
html.dark .gen-card-blob-a { background: #2f5bd3; }
html.dark .gen-card-blob-b { background: #6d3fc4; }
html.dark .gen-card-sweep { background: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, 0.14) 50%, transparent 58%); }
html.dark .gen-card-line { color: #eef2ff; }
html.dark .gen-card-title { color: #f0f2f8; }
html.dark .gen-card-time, html.dark .gen-card-status { color: #aab4c4; }
html.dark .gen-card-bar { background: #2a3140; }
html.dark .gen-card-bar > span { background: linear-gradient(90deg, #8ab4ff, #b794f6); }
html.dark .gen-card-action { background: #0f131a; border-color: #2f3746; color: #8ab4ff; }
html.dark .gen-card-action:hover { border-color: #8ab4ff; background: #1c2433; }
html.dark .gen-card-action:focus-visible { outline-color: #8ab4ff; }
html.dark .gen-card.is-failed .gen-card-frame { background: #2a1717; }
html.dark .gen-card-error .material-symbols-outlined { color: #ffb4ab; }
html.dark .gen-card-error p { color: #f0f2f8; }
html.dark .gen-card.is-done .gen-card-frame { background: #000000; }

@media (prefers-reduced-motion: reduce) {
  .gen-card, .gen-card.is-loading,
  .gen-card-paint, .gen-card-blob, .gen-card-sweep { animation: none !important; }
  .gen-card-sweep { display: none; }
  .gen-card-line, .gen-card-bar > span { transition: none; }
}
