@import "tailwindcss";
@import "swiper/css";
@import "swiper/css/free-mode";
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

/* The app's dark mode is a manual user choice (stored as [data-theme="dark"]
   on <html>), not the OS preference, so `dark:` utilities must key off that
   attribute instead of Tailwind's default `prefers-color-scheme` variant. */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));

/* One-shot correct/incorrect flashes used by the matching activities.
   Exposed as `animate-flash-success` / `animate-flash-error` utilities. */
@theme {
  --animate-flash-success: flash-success 0.6s ease-out;
  --animate-flash-error: flash-error 0.6s ease-out;
}
@keyframes flash-success {
  0% { background-color: rgb(34, 197, 94); }
  100% { background-color: transparent; }
}
@keyframes flash-error {
  0% { background-color: rgb(239, 68, 68); }
  100% { background-color: transparent; }
}

  body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
    /* Smooth scrolling for a more polished feel */
    scroll-behavior: smooth;
    /* Antialiasing for crisp text */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    min-height: 100dvh;
    /* viewport-fit=cover makes the page extend behind the status bar / native
       nav bar (webview); keep content below it. Bottom insets are handled
       per-screen so action bars can paint their background into the inset. */
    padding-top: env(safe-area-inset-top, 0px);
  }

/* Full-height app screens (fixed column, internal scroll). Plain 100dvh would
   overflow the bottom by the top inset now that body pads the top. */
@utility h-dvh-safe {
  height: calc(100dvh - env(safe-area-inset-top, 0px));
  max-height: calc(100dvh - env(safe-area-inset-top, 0px));
}

  @keyframes float {

    0%,
    100% {
      transform: translateY(0);
    }

    50% {
      transform: translateY(-8px);
    }
  }

  .float-animate {
    animation: float 2.5s ease-in-out infinite;
    /* Slightly slower animation for a more gentle float */
  }

  /* Custom scrollbar for a more integrated dark theme look (optional, but a nice touch) */
  ::-webkit-scrollbar {
    width: 10px;
  }

  ::-webkit-scrollbar-track {
    background: var(--color-gray-100);
  }

  ::-webkit-scrollbar-thumb {
    background: var(--color-gray-300);
    border-radius: 5px;
  }

  ::-webkit-scrollbar-thumb:hover {
    background: var(--color-gray-400);
  }

  [data-theme="dark"] ::-webkit-scrollbar-track {
    background: var(--color-gray-900);
  }

  [data-theme="dark"] ::-webkit-scrollbar-thumb {
    background: var(--color-gray-700);
  }

  [data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
    background: var(--color-gray-600);
  }


  @keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes fade-out {
  to {
    opacity: 0;
  }
}

@keyframes slide-from-right {
  from {
    transform: translateX(60px);
  }
}

@keyframes slide-up {
  from {
    transform: translateY(130px);
  }
}

@keyframes slide-to-left {
  to {
    transform: translateX(-30px);
  }
}

/* Global but more fancy */
::view-transition-old(root) {
  animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
  animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

/* Swiper specific fixes */
.swiper {
  width: 100%;
  overflow: hidden;
}

.swiper-wrapper {
  display: flex;
  align-items: stretch;
}

.swiper-slide {
  flex-shrink: 0;
  width: auto !important;
  height: auto;
}

/* Mobile specific fixes */
@media (max-width: 768px) {
  body, html {
    overflow-x: hidden;
    max-width: 100vw;
  }
  
  main {
    overflow-x: hidden;
    max-width: 100vw;
  }
  
  .swiper {
    overflow: hidden;
    margin-left: calc(-1rem);
    margin-right: calc(-1rem);
    padding-left: 1rem;
    padding-right: 1rem;
    width: calc(100vw - 2rem);
  }
  
  .swiper-slide {
    margin-right: 1rem;
  }
  
  /* Fix grid width on mobile */
  .grid {
    padding-left: 0;
    padding-right: 0;
    max-width: 100%;
  }
  
  /* Ensure course cards don't cause overflow */
  .grid > div {
    min-width: 0;
    max-width: 100%;
  }
  
  /* Ensure sections don't overflow */
  section {
    max-width: 100vw;
    overflow-x: hidden;
  }
}
/* ---------------------------------------------------------------------------
   langlets. mobile app (app/views/app/**)
   ---------------------------------------------------------------------------
   Tokens for the native-app screens, taken from the "Turn iOS App" mockup.
   Namespaced `app-*` so they can't collide with the web palette above.

   IMPORTANT: never use `dark:` utilities under app/views/app/**. These screens
   are dark-only and layouts/app.html.erb hard-codes data-theme="dark", so a
   partial copied over from the web would have its dark:-conditional styling
   silently become unconditional. Use these tokens literally.
--------------------------------------------------------------------------- */
@theme {
  --color-app-bg: #0A1521;         /* screen background */
  --color-app-card: #11202F;       /* cards */
  --color-app-sheet: #101D2B;      /* bottom sheets */
  --color-app-inset: #0A1521;      /* recessed fields inside a sheet */
  --color-app-pill: #1B2C3C;       /* credits pill, avatar, close button */
  --color-app-chip: #1A2A39;       /* inactive chip, micro-tag */
  --color-app-segment: #1E3140;    /* active segmented-control segment */

  --color-app-accent: #1DC77C;
  /* Two on-accent colours, and the difference is real: the mockup uses #052012
     on the large pill CTAs and #04170E on badges, chips, the FAB glyph and
     check marks. One token would rot the distinction. */
  --color-app-on-accent: #052012;
  --color-app-on-accent-sm: #04170E;

  --color-app-text: #FFFFFF;
  --color-app-text-2: #8FA0AE;     /* secondary */
  --color-app-text-3: #66788A;     /* tertiary / footnotes / placeholders */
  --color-app-text-dim: #A9B7C2;   /* settings labels, dimmed titles */
  --color-app-credits: #E7EDF2;    /* the number in the credits pill */

  --radius-app-sheet: 28px;
  --radius-app-hero: 20px;
  --radius-app-card: 16px;
  --radius-app-field: 14px;
  --radius-app-input: 12px;
  --radius-app-thumb: 10px;

  /* The mockup is SF Pro, not the Inter the web app loads. */
  --font-app: -apple-system, "SF Pro Text", "Helvetica Neue", system-ui, sans-serif;
}

/* 0.5px borders and backdrop blur don't express cleanly as Tailwind utilities. */
@utility app-hairline {
  border: 0.5px solid rgb(255 255 255 / 0.07);
}

@utility app-hairline-t {
  border-top: 0.5px solid rgb(255 255 255 / 0.08);
}

/* Cards separate by border alone — the mockup has no elevation on them. */
@utility app-tabbar {
  background: rgb(7 15 23 / 0.9);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-top: 0.5px solid rgb(255 255 255 / 0.08);
}

/* The only shadow in the whole design. */
@utility app-fab-shadow {
  box-shadow: 0 6px 18px rgb(29 199 124 / 0.35);
}

/* "Ready" queue card: accent-tinted border rather than a fill. */
@utility app-border-ready {
  border: 0.5px solid rgb(29 199 124 / 0.35);
}

/* "Queued" queue card: dashed outline, no fill. */
@utility app-border-queued {
  border: 1.5px dashed rgb(255 255 255 / 0.14);
}

@utility app-sheet-top {
  border-top: 0.5px solid rgb(255 255 255 / 0.1);
}

/* Recessed field inside a sheet. */
@utility app-inset-hairline {
  border: 0.5px solid rgb(255 255 255 / 0.1);
}

/* Two lines, then ellipsis — library card titles. */
@utility app-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Screens scroll under a fixed tab bar; without this the last card hides
   behind it. Tab bar is 10px top + 24px icon + 3px gap + 10px label + 30px
   bottom padding, plus the home-indicator inset. */
@utility app-scroll-pad {
  padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}

/* In the 2.x app builds (data-native-tabs on <body>) the tab bar is native and
   already inside the safe-area inset, so the pad only clears the floating Add
   button: 18px gap + 44px button + 18px breathing room. */
[data-native-tabs] .app-scroll-pad {
  padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
}

/* Course pages still use the regular web layout inside the 2.x native app.
   Keep their playlist sheet above the native UITabBar and reduce its available
   height by the same amount so its controls never extend behind the bar. */
.playlist-sheet-overlay {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.playlist-sheet {
  max-height: min(85dvh, calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 16px));
}

[data-native-tabs] .playlist-sheet-overlay {
  padding-bottom: calc(49px + env(safe-area-inset-bottom, 0px));
}

[data-native-tabs] .playlist-sheet {
  max-height: min(85dvh, calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 65px));
}
