@import "tailwindcss";

/* Tailwind v4 doesn't scan .erb files by default (and may miss arbitrary */
/* value classes from non-standard file types). Explicit globs ensure */
/* every class — including text-[10px], aspect-[16/5], etc. — is detected. */
@source "../../../app/views/**/*.html.erb";
@source "../../../app/views/**/*.erb";
@source "../../../app/components/**/*.erb";
@source "../../../app/components/**/*.rb";
@source "../../../app/helpers/**/*.rb";
@source "../../../app/javascript/**/*.js";

/* ---------------------------------------------------------------- */
/* Pageant Post — Design System                                     */
/* Brand: premium mobile-app feel. Instagram, not GoDaddy.          */
/* ---------------------------------------------------------------- */

@theme {
  /* Plum (primary — regal, pageant-luxurious) */
  --color-plum-50: #f9f4f7;
  --color-plum-100: #f0e1ec;
  --color-plum-200: #dbb8d0;
  --color-plum-300: #b685a8;
  --color-plum-400: #855675;
  --color-plum-500: #4A1942;
  --color-plum-600: #3d1438;
  --color-plum-700: #2e0f2a;
  --color-plum-800: #20091d;
  --color-plum-900: #14091a;
  --color-plum-950: #0a040d;

  /* Gold (accent — crown, trophy, winner) */
  --color-gold-50: #fbf6ea;
  --color-gold-100: #f7eccd;
  --color-gold-200: #efd698;
  --color-gold-300: #e8c481;
  --color-gold-400: #dcb46c;
  --color-gold-500: #D4A857;
  --color-gold-600: #b88f3f;
  --color-gold-700: #8d6b2f;
  --color-gold-800: #614920;
  --color-gold-900: #3a2c14;

  /* Ivory (warm light background — never stark white) */
  --color-ivory-50: #fefcf8;
  --color-ivory-100: #faf6f0;
  --color-ivory-200: #f4ecdc;
  --color-ivory-300: #e6ddd0;

  /* Wine (deep dark background — default mode) */
  --color-wine-900: #241326;
  --color-wine-950: #14091a;
  --color-wine-darker: #0a040d;

  /* Semantic */
  --color-success: #5A8A5A;
  --color-success-light: #7eaa7e;
  --color-danger: #B14545;
  --color-danger-light: #d06868;
  --color-warning: #C8893A;
  /* Cool informational accent — the ONE cool tone in the warm palette,
     for "informational, not actionable" (feed comments/notes, info
     callouts). Desaturated so it sits quietly in the wine world. */
  --color-info: #5B8A9A;
  --color-info-light: #7fa9b8;

  /* Typography */
  --font-display: "DM Serif Display", Georgia, serif;
  --font-sans: "Inter", system-ui, -apple-system, sans-serif;
  --font-mono: "Inter", "SF Mono", monospace;

  /* Spacing (4px base) */
  --spacing-touch: 2.75rem;    /* 44px minimum touch target */
  --spacing-touch-lg: 3rem;     /* 48px ideal */

  /* Radii */
  --radius-button: 0.75rem;     /* 12px */
  --radius-card: 1rem;          /* 16px */
  --radius-input: 0.5rem;       /* 8px */
  --radius-pill: 999px;

  /* Shadows — multi-layer, subtle */
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.10), 0 2px 4px -2px rgb(0 0 0 / 0.06);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.15), 0 4px 6px -4px rgb(0 0 0 / 0.08);
  --shadow-glow-gold: 0 0 24px -4px rgb(212 168 87 / 0.4);
}

/* ---------------------------------------------------------------- */
/* Base — mobile-first, dark default                                 */
/* ---------------------------------------------------------------- */

@layer base {
  /* Dock offset — how far UP from the viewport bottom the floating glass
     pills (and the scroll clearance) must shift to sit above fixed bottom
     chrome. 0 by default; when the mobile bottom nav is on the page
     (data-dock="bottom-nav", visible below sm only) it grows by the nav's
     height. Anything new that docks to the bottom edge must set/consume
     THIS variable, never hardcode its own offset. */
  :root {
    --dock-offset: 0px;
  }
  @media (max-width: 639px) {
    body:has([data-dock="bottom-nav"]) {
      --dock-offset: calc(52px + env(safe-area-inset-bottom));
    }
  }

  /* Floating-pill scroll clearance — every layout, every device size.
     Content must always scroll past the fixed glass pills (back circle,
     manage, save), including the bottom nav and the iOS home-indicator
     safe area. Set HERE once; never pad an individual page or layout
     for the pills. */
  main {
    padding-bottom: calc(7rem + var(--dock-offset) + env(safe-area-inset-bottom));
  }

  /* iOS Safari gives date/time inputs an intrinsic width that ignores
     width:100% and bleeds past the card edge — normalize them to behave
     like every other input. */
  input[type="date"],
  input[type="datetime-local"],
  input[type="time"] {
    -webkit-appearance: none;
    appearance: none;
    /* flex + center: iOS top-aligns the value box inside fixed-height
       inputs; centering the input's content fixes the high-riding text. */
    display: flex;
    align-items: center;
    width: 100%;
    min-width: 0;
    max-width: 100%;
  }
  /* iOS centers the value and collapses it when empty — left-align and
     give it height so the field doesn't render as a sliver. */
  input::-webkit-date-and-time-value {
    text-align: left;
    min-height: 1.5em;
  }

  /* Checkboxes and radios pick up the brand gold, not the OS default blue. */
  input[type="checkbox"],
  input[type="radio"] {
    accent-color: var(--color-gold-500);
  }

  html {
    /* Prevent iOS Safari text-size adjust on orientation change */
    -webkit-text-size-adjust: 100%;
    /* Smooth font rendering */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Min font size — never under 16px for mobile readability */
    font-size: 16px;
  }

  body {
    background-color: var(--color-wine-950);
    color: var(--color-ivory-200);
    font-family: var(--font-sans);
    line-height: 1.5;
    /* Prevent horizontal scroll on mobile */
    overflow-x: hidden;
  }

  h1, h2, h3, h4 {
    font-family: var(--font-display);
    line-height: 1.2;
    letter-spacing: -0.01em;
  }

  /* Disable double-tap zoom on buttons (iOS) */
  button, a, [role="button"] {
    touch-action: manipulation;
  }
}

/* ---------------------------------------------------------------- */
/* Reusable component patterns                                      */
/* ---------------------------------------------------------------- */

@layer components {
  /* Primary button — gold CTA */
  .btn-primary {
    @apply inline-flex items-center justify-center gap-2 px-6 min-h-[44px] rounded-xl bg-gold-500 text-wine-950 font-semibold text-base transition-all active:scale-[0.98] hover:bg-gold-400 disabled:opacity-50 disabled:cursor-not-allowed;
  }

  /* Floating badge that straddles a border (Popular, 2 months free, demo
     frame labels). ALWAYS solid: a translucent badge lets the border line
     run through the text and read as strikethrough. Position utilities
     (absolute offsets) stay at the call site. */
  .edge-badge {
    @apply absolute z-10 px-2.5 py-0.5 rounded-full bg-gold-500 text-wine-950 text-[10px] font-bold uppercase tracking-wider whitespace-nowrap;
  }

  /* Inline gold link — THE recipe for every gold text link. Add sizing,
     weight, underline, or layout utilities at the call site; never re-roll
     the gold pair itself. */
  .link-gold {
    @apply text-gold-400 hover:text-gold-300 transition;
  }

  /* Secondary button — plum outline */
  .btn-secondary {
    @apply inline-flex items-center justify-center gap-2 px-6 min-h-[44px] rounded-xl border border-plum-300 text-ivory-200 font-medium text-base transition-all active:scale-[0.98] hover:bg-plum-700;
  }

  /* Ghost button */
  .btn-ghost {
    @apply inline-flex items-center justify-center gap-2 px-4 min-h-[44px] rounded-xl text-ivory-200 font-medium text-base transition-all active:scale-[0.98] hover:bg-plum-700;
  }

  /* Native <select> wearing .input — keep the device's native picker
     (the OS sheet on iOS is a feature), but restyle the CLOSED control:
     appearance-none kills the default arrow that hugs the right edge,
     and we draw a brand chevron at the same inset as the text padding.
     Applies to every select.input automatically — no extra class. */
  select.input {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.75rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b685a8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    background-size: 1.125rem;
    cursor: pointer;
  }

  /* Liquid-glass floating pill — THE recipe for every fixed floating
     control (back button, owner manage pill, search loading pill).
     Blur + saturate the page behind it, hairline light border, inner
     top highlight for the glass edge. Add position/size utilities at
     the call site; never re-roll the glass itself. */
  .glass-pill {
    @apply inline-flex items-center rounded-full bg-wine-900/50 border border-ivory-100/15 text-sm text-ivory-100 transition;
    backdrop-filter: blur(24px) saturate(1.5);
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 8px 24px rgba(0, 0, 0, 0.35);
    /* Docking is owned HERE so every pill rises above bottom chrome
       (mobile bottom nav) together. Call sites set only left/right. */
    position: fixed;
    bottom: calc(1.5rem + var(--dock-offset));
    z-index: 40;
  }

  /* Card */
  .card {
    @apply rounded-2xl bg-wine-900 border border-plum-700 p-4 sm:p-6;
  }

  /* Row item — the contained list row used inside cards (scoring hub
     areas/penalties, crowning titles, slice sub-scores). One recipe. */
  .row-item {
    @apply flex items-center gap-3 py-2.5 px-3 rounded-xl bg-plum-900/40 border border-plum-700/40;
  }

  /* The "+ Add …" section-header link */
  .link-add {
    @apply text-xs font-semibold text-gold-400 hover:text-gold-300 transition;
  }

  /* Input — bg darker than the card it sits inside, border slightly */
  /* brighter than the card's border, so inputs read as "inset" and */
  /* are visually distinct even before focus. */
  /* The app always renders its own clear × on search inputs (search-bar
     controller) — hide the browser's native one so they never double up. */
  input[type="search"]::-webkit-search-cancel-button,
  input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
  }

  .input {
    /* py matters even with min-h: inputs center their text, but textareas
       start at the top — without padding the text touches the border. */
    @apply w-full min-h-[44px] px-4 py-2.5 rounded-lg bg-wine-950 border border-plum-600 text-ivory-100 placeholder:text-plum-300 focus:border-gold-500 focus:outline-none focus:ring-2 focus:ring-gold-500/30 transition;
  }

  /* Drag-and-drop file zone — THE file picker (shared/_file_drop +
     file-drop controller). Replaced the old .input-file native control.
     A label wrapping the whole zone makes tap-to-browse free; the
     controller toggles .is-dragging while a drag hovers the zone. */
  .file-drop {
    @apply flex flex-col items-center justify-center gap-1.5 w-full min-h-[7.5rem] px-4 py-5 rounded-xl border-2 border-dashed border-plum-600 bg-wine-950/70 text-center cursor-pointer transition-colors;
  }
  .file-drop:hover,
  .file-drop.is-dragging {
    border-color: color-mix(in srgb, var(--color-gold-500) 60%, transparent);
    background-color: color-mix(in srgb, var(--color-plum-900) 40%, transparent);
  }
  /* The real input sits sr-only just before the label — light the zone
     when keyboard focus lands on it. */
  .file-drop-input:focus-visible + .file-drop {
    @apply border-gold-500/60 ring-2 ring-gold-500/30;
  }
  .file-drop-icon {
    @apply w-6 h-6 text-gold-400;
  }
  .file-drop-primary {
    @apply text-sm font-medium text-ivory-200;
  }
  .file-drop-secondary {
    @apply text-[11px] text-plum-300;
  }

  /* Public pageant page hero banner — responsive aspect ratio + min/max heights. */
  /* Defined here because Tailwind v4 doesn't extract bracket-arbitrary classes */
  /* like aspect-[16/5] from .erb files. */
  .pageant-banner {
    position: relative;
    width: 100%;
    background-color: var(--color-plum-800);
    aspect-ratio: 5 / 2;       /* mobile: shorter, banner-ish */
    min-height: 10rem;          /* 160px */
    max-height: 21.25rem;       /* 340px */
  }
  @media (min-width: 640px) {
    .pageant-banner {
      aspect-ratio: 3 / 1;     /* tablet */
      min-height: 12.5rem;      /* 200px */
    }
  }
  @media (min-width: 1024px) {
    .pageant-banner {
      aspect-ratio: 16 / 5;    /* desktop: wide hero */
      min-height: 15rem;        /* 240px */
    }
  }

  /* ------------------------------------------------------------ */
  /* Pro upgrade page — tasteful, CSS-only motion. Every animation */
  /* lives inside the reduced-motion guard below; without it these */
  /* classes render a perfectly good static page.                  */
  /* ------------------------------------------------------------ */

  /* Slow gold shimmer sweeping across the hero headline. The gradient
     text is static until the media query below sets it in motion.
     Applied to an inline-block SPAN inside the heading: clipped text only
     paints inside the padding box, and DM Serif descenders (the j in
     "majors") poke below a 1.2 line box and get cut, so pad the paint box
     out on every side and pull layout back in with matching margins. */
  .pro-shimmer {
    display: inline-block;
    padding: 0.15em 0.15em 0.3em;
    margin: -0.15em -0.15em -0.3em;
    background-image: linear-gradient(105deg,
      var(--color-ivory-100) 38%,
      var(--color-gold-300) 50%,
      var(--color-ivory-100) 62%);
    background-size: 220% 100%;
    background-position: 50% 0;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  /* The hero crown: gold glow always, gentle float only with motion. */
  .pro-crown {
    filter: drop-shadow(0 0 18px rgb(212 168 87 / 0.45));
  }

  /* Scroll reveal (scroll-reveal Stimulus controller): the controller adds
     .reveal-hidden on connect — never in the markup, so content stays fully
     visible without JS — then .reveal-in as each item enters the viewport.
     Both classes are no-ops for reduced-motion users. */
  @media (prefers-reduced-motion: no-preference) {
    .pro-shimmer {
      animation: pro-shimmer 6s linear infinite;
    }
    .pro-float {
      animation: pro-float 5s ease-in-out infinite;
    }
    .reveal-hidden {
      opacity: 0;
      transform: translateY(16px);
    }
    .reveal-in {
      opacity: 1;
      transform: translateY(0);
      transition: opacity 0.6s ease, transform 0.6s ease;
    }
  }

  /* Compact version for the director's preview hero on /director/pageants/:id */
  .pageant-banner-compact {
    position: relative;
    width: 100%;
    background-color: var(--color-plum-800);
    aspect-ratio: 5 / 2;
    min-height: 8.75rem;        /* 140px */
    max-height: 17.5rem;        /* 280px */
  }
  @media (min-width: 640px) {
    .pageant-banner-compact {
      aspect-ratio: 3 / 1;
      min-height: 11.25rem;     /* 180px */
    }
  }
  @media (min-width: 1024px) {
    .pageant-banner-compact {
      aspect-ratio: 16 / 5;
      min-height: 13.75rem;     /* 220px */
    }
  }
}

/* Keyframes for the Pro upgrade page (used only inside the
   prefers-reduced-motion guard above). */
@keyframes pro-shimmer {
  from { background-position: 160% 0; }
  to   { background-position: -60% 0; }
}
@keyframes pro-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}
