@import "tailwindcss";

/* ---------------------------------------------------------------------------
   Data tables

   Flat, Stripe-dashboard style: no card border or drop shadow around the
   table, no filled header band, hairline rules between rows, and a quiet
   hover. Defined once here so every table in the admin stays consistent and
   the ERB stays readable.

   Markup contract:
     <div class="data-table-wrap">
       <table class="data-table"> … </table>
       <p class="data-table-empty">Nothing here yet.</p>   (optional)
     </div>

   The first column is emphasised automatically — it is the row's identity in
   every table we have.
   --------------------------------------------------------------------------- */
@layer components {
  .data-table-wrap {
    @apply mt-6 overflow-x-auto;
  }

  .data-table {
    @apply min-w-full border-collapse text-sm;
  }

  .data-table thead th {
    @apply whitespace-nowrap border-b border-gray-200 px-3 py-2.5 text-left text-sm font-semibold text-gray-700;
  }

  .data-table tbody tr {
    @apply border-b border-gray-100 transition-colors;
  }

  .data-table tbody tr:hover {
    @apply bg-gray-50;
  }

  .data-table tbody td {
    @apply px-3 py-3.5 align-middle text-sm text-gray-600;
  }

  .data-table tbody td:first-child {
    @apply font-medium text-gray-900;
  }

  /* Sit the outer columns flush with the page heading above the table. */
  .data-table th:first-child,
  .data-table td:first-child {
    @apply pl-1;
  }

  .data-table th:last-child,
  .data-table td:last-child {
    @apply pr-1;
  }

  .data-table-empty {
    @apply py-12 text-center text-sm text-gray-500;
  }

  /* Row affordance on the right-hand side, e.g. "Score →". */
  .data-table-action {
    @apply text-right font-medium text-indigo-600;
  }

  /* ------------------------------------------------------------------------
     Badges — a small rounded rectangle with a hairline ring, not a full pill.
     ------------------------------------------------------------------------ */
  .badge {
    @apply inline-flex items-center rounded-md px-2 py-0.5 text-xs font-medium ring-1 ring-inset;
  }

  .badge-gray {
    @apply bg-gray-50 text-gray-600 ring-gray-200;
  }

  .badge-green {
    @apply bg-green-50 text-green-700 ring-green-200;
  }

  .badge-indigo {
    @apply bg-indigo-50 text-indigo-700 ring-indigo-200;
  }

  .badge-yellow {
    @apply bg-yellow-50 text-yellow-800 ring-yellow-200;
  }

  .badge-red {
    @apply bg-red-50 text-red-700 ring-red-200;
  }
}

@layer components {
  /* ------------------------------------------------------------------------
     Combobox — a text field with a suggestion list. Used for party series and
     for venues; both allow free text, so this is a shortcut, not a picker.
     ------------------------------------------------------------------------ */
  .combobox {
    @apply relative;
  }

  .combobox-list {
    @apply absolute z-20 mt-1 max-h-64 w-full overflow-auto rounded-md border border-gray-200 bg-white py-1 shadow-lg;
  }

  .combobox-option {
    @apply cursor-pointer px-3 py-2 text-sm text-gray-900 hover:bg-indigo-50;
  }

  .combobox-option.is-active {
    @apply bg-indigo-50;
  }

  .combobox-option-name {
    @apply block font-medium;
  }

  .combobox-option-detail {
    @apply block text-xs text-gray-500;
  }

  /* The address of whatever was last picked. Collapses away entirely while the
     field holds something typed by hand, which has no record behind it. */
  .combobox-detail {
    @apply mt-1 block text-xs text-gray-500;
  }

  .combobox-detail:empty {
    @apply hidden;
  }

  /* Shared form field styling, so the markup stops repeating a dozen classes. */
  .form-label {
    @apply block text-sm font-medium text-gray-700;
  }

  .form-input {
    @apply mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm sm:text-sm focus:border-indigo-500 focus:ring-indigo-500;
  }

  /* ------------------------------------------------------------------------
     Flash — pinned bottom centre, out of the way of the page heading.
     ------------------------------------------------------------------------ */
  .flash-dock {
    @apply pointer-events-none fixed inset-x-0 bottom-6 z-50 flex flex-col items-center gap-2 px-4;
  }

  .flash-message {
    @apply pointer-events-auto flex items-center gap-2 rounded-lg px-4 py-3 text-sm font-medium shadow-lg ring-1;
  }

  .flash-notice {
    @apply bg-green-50 text-green-800 ring-green-200;
  }

  .flash-alert {
    @apply bg-red-50 text-red-800 ring-red-200;
  }
}

@layer components {
  /* ------------------------------------------------------------------------
     Flyers — a single horizontally scrolling row of draggable tiles.
     ------------------------------------------------------------------------ */
  .flyer-row {
    @apply flex snap-x gap-4 overflow-x-auto pb-2;
  }

  .flyer-tile {
    @apply relative w-40 flex-none cursor-grab snap-start rounded-md border border-gray-200 bg-gray-50;
  }

  /* The first flyer is the one that represents the party. */
  .flyer-tile.is-main {
    @apply border-indigo-500 ring-2 ring-indigo-500;
  }

  .flyer-main-label {
    @apply hidden pt-1 text-center text-xs font-semibold text-indigo-700;
  }

  .flyer-tile.is-main .flyer-main-label {
    @apply block;
  }

  /* Tailwind's Preflight sets `margin: 0` on every element, which defeats the
     `margin: auto` a native <dialog> relies on to centre itself. */
  .upload-dialog {
    @apply m-auto w-96 max-w-[90vw] rounded-lg border border-gray-200 p-5 shadow-xl backdrop:bg-gray-900/40;
  }

  /* The two CSV uploads in the sync modal. The browser's own file control says
     "No file chosen" in text that cannot be styled and leaves nowhere to put
     the export instructions, so it is hidden behind this frame. */
  .upload-drop {
    @apply rounded-lg border border-dashed border-gray-300 bg-gray-50/60 transition-colors;
  }

  .upload-drop:hover,
  .upload-drop:focus-within {
    @apply border-gray-400 bg-gray-50;
  }

  .upload-drop-active {
    @apply border-indigo-400 bg-indigo-50;
  }

  .upload-drop-filled {
    @apply border-solid border-green-300 bg-green-50/40;
  }

  .upload-drop-prompt,
  .upload-drop-chosen {
    @apply mt-3 flex items-center gap-2 text-sm text-gray-600;
  }

  .upload-drop-chosen {
    @apply text-gray-900;
  }

  .sync-dialog {
    @apply m-auto w-[32rem] max-w-[90vw] rounded-lg border border-gray-200 p-6 shadow-xl backdrop:bg-gray-900/40;
  }

  /* A sync runs for minutes with long quiet stretches; the spinner is the only
     thing on the page that says it is still alive. */
  .sync-spinner {
    @apply inline-block h-4 w-4 flex-shrink-0 animate-spin rounded-full border-2 border-indigo-300 border-t-indigo-700;
  }

  /* Two fields and a pair of buttons — narrower than the sync dialog, and with
     room under the series field for its suggestion list to hang open. */
  .party-dialog {
    @apply m-auto w-[26rem] max-w-[90vw] overflow-visible rounded-lg border border-gray-200 p-6 shadow-xl backdrop:bg-gray-900/40;
  }

  .flyer-dialog {
    @apply m-auto w-80 max-w-[90vw] rounded-lg border border-gray-200 p-5 shadow-xl backdrop:bg-gray-900/40;
  }

  .flyer-tile:focus-visible {
    @apply outline-none ring-2 ring-indigo-500 ring-offset-2;
  }

  .flyer-tile.is-dragging {
    @apply cursor-grabbing opacity-40;
  }

  /* Tracklist rows use the same dragging state as flyer tiles. */
  li.is-dragging {
    @apply opacity-40;
  }

  /* Chosen in the browser but not yet uploaded. */
  .flyer-tile.is-pending {
    @apply border-dashed border-amber-400 bg-amber-50;
  }

  .flyer-thumb {
    @apply aspect-[3/4] w-full bg-white object-contain;
  }

  .flyer-tile-footer {
    @apply flex items-center justify-between gap-1 border-t border-gray-200 bg-white px-2 py-1.5 text-xs text-gray-600;
  }

  .flyer-tile-add {
    @apply flex aspect-[3/4] w-40 flex-none items-center justify-center rounded-md border-2 border-dashed border-gray-300 hover:border-indigo-400 hover:bg-indigo-50/40;
  }
}

/* Notes read as supporting detail rather than body copy, so the editor and the
   rendered content are set noticeably smaller than the rest of the form. */
lexxy-editor .lexxy-editor__content,
.lexxy-content {
  font-size: 0.6875rem;
  line-height: 1.5;
}

/* The notes column is the tallest thing on the party form; give it real room —
   but only once it is a column. Stacked on a narrow screen it would otherwise
   push everything below it off the page. */
.notes-field lexxy-editor {
  min-height: 12rem;
}

@media (min-width: 64rem) {
  .notes-field lexxy-editor {
    min-height: 26rem;
  }
}

/* A panelist's comment is the one piece of writing on their ballot, so the
   box starts tall and the text is set at reading size rather than the small
   size used for notes. */
.ballot-comment-field lexxy-editor {
  min-height: 18rem;
}

.ballot-comment-field lexxy-editor .lexxy-editor__content {
  font-size: 0.875rem;
}
