@import "tailwindcss";
@plugin "@tailwindcss/forms";

/* Tailwind 4 scans sources relative to this file. */
@source "../../views";
@source "../../helpers";
@source "../../javascript";

/* Desktop sidebar reduced to its icons (layouts/admin, sidebar_controller.js). The flag
   sits on the wrapper of sidebar and content, not on the mobile drawer. */
@custom-variant sidebar-collapsed (&:where([data-sidebar-collapsed="true"] *));

@theme {
  /* Taxfolio accent (emerald, see landing/auth); neutral surfaces stay slate/gray. */
  --color-primary-50: var(--color-emerald-50);
  --color-primary-100: var(--color-emerald-100);
  --color-primary-200: var(--color-emerald-200);
  --color-primary-300: var(--color-emerald-300);
  --color-primary-400: var(--color-emerald-400);
  --color-primary-500: var(--color-emerald-500);
  --color-primary-600: var(--color-emerald-600);
  --color-primary-700: var(--color-emerald-700);
  --color-primary-800: var(--color-emerald-800);
  --color-primary-900: var(--color-emerald-900);

  /* Brand accent from the logo (petrol grey → steel blue → navy), used for tabs. */
  --color-accent-50: #eef3f6;
  --color-accent-100: #dbe5eb;
  --color-accent-300: #9fb4bf;
  --color-accent-500: #58787f;
  --color-accent-600: #466073;
  --color-accent-700: #395066;
  --color-accent-900: #2f4060;

  --container-8xl: 88rem;
}

@layer base {
  /* Tailwind 4 resets buttons to cursor: default. */
  button:not(:disabled),
  [role="button"]:not(:disabled) {
    cursor: pointer;
  }

  /* Native popovers start hidden; the dropdown controller positions them on open. */
  [popover] {
    inset: auto;
  }
}

@layer components {
  .container {
    @apply px-4 sm:px-6 lg:px-8;
  }

  /* Breaks out of a padded parent (dialog body, .container) to span its full width.
     The admin content column itself has no horizontal padding, so tables sit flush
     against the edges and non-table content wraps itself in .container. */
  .full-width {
    @apply -mx-4 sm:-mx-6;
  }

  /* --- Typography ------------------------------------------------------ */

  .headline {
    @apply text-2xl font-semibold leading-6 text-gray-900;
  }

  .text {
    @apply text-sm text-gray-700;
  }

  /* --- Forms ------------------------------------------------------------ */

  .form-label {
    @apply block text-sm/6 font-medium text-gray-900;
  }

  .form-control {
    @apply block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-xs ring-1 ring-gray-300 ring-inset placeholder:text-gray-400 focus:ring-2 focus:ring-primary-600 focus:ring-inset sm:text-sm/6 disabled:cursor-not-allowed disabled:opacity-50;
  }

  .form-check-input {
    @apply size-4 rounded-sm border-gray-300 text-primary-600 focus:ring-primary-500;
  }

  .form-radio-input {
    @apply size-4 border-gray-300 text-primary-600 focus:ring-primary-500;
  }

  .form-check-label {
    @apply pl-3 text-sm/6 text-gray-900;
  }

  .form-hint {
    @apply mt-1 text-xs text-gray-500;
  }

  /* --- Buttons ---------------------------------------------------------- */

  .btn {
    @apply block rounded-md bg-slate-900 px-3 py-2 text-center text-sm font-semibold text-white shadow-xs hover:bg-slate-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 disabled:cursor-not-allowed disabled:opacity-50;
  }

  .btn-secondary {
    @apply block rounded-md bg-white px-3 py-2 text-center text-sm font-semibold text-gray-900 shadow-xs ring-1 ring-gray-300 ring-inset hover:bg-gray-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600;
  }

  .btn-table-primary {
    @apply inline-flex items-center gap-x-1.5 rounded-md bg-slate-900 px-2.5 py-1.5 text-sm/6 font-medium whitespace-nowrap text-white shadow-xs hover:bg-slate-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600;
  }

  .btn-table-light {
    @apply inline-flex items-center gap-x-1.5 rounded-md bg-white px-2.5 py-1.5 text-sm/6 font-medium whitespace-nowrap text-gray-900 shadow-xs ring-1 ring-gray-300 ring-inset hover:bg-gray-50;
  }

  /* --- Tabs ------------------------------------------------------------- */

  /* The underline is an inset shadow instead of a border, so it is drawn inside the
     tab and its thickness does not change the tab's height. */
  .tab {
    @apply px-1 py-4 text-sm font-medium whitespace-nowrap data-[current=true]:text-accent-700 data-[current=true]:shadow-[inset_0_-3px_0_0_var(--color-accent-600)] data-[current=false]:text-gray-500 hover:data-[current=false]:text-gray-700 hover:data-[current=false]:shadow-[inset_0_-3px_0_0_var(--color-gray-300)];
  }

  .tab-badge {
    @apply ml-2 hidden rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-900 md:inline-block data-[current=true]:bg-accent-100 data-[current=true]:text-accent-700;
  }

  /* --- Dropdown menus (popover content) --------------------------------- */

  .dropdown-menu {
    @apply m-0 w-56 rounded-md bg-white p-0 py-1 shadow-lg ring-1 ring-black/5 outline-hidden;
  }

  .dropdown-menu a,
  .dropdown-menu button {
    @apply block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 focus:bg-gray-100 focus:text-gray-900 focus:outline-hidden;
  }

  .dropdown-menu .danger {
    @apply text-red-700 hover:bg-red-50;
  }

  /* --- Collapsible sidebar --------------------------------------------- */

  /* Only shown in the expanded sidebar (title, link labels, footer). Collapsing takes it
     out of the flow at once, so nothing overflows while the width shrinks; expanding
     fades it in once the width has mostly caught up. */
  .sidebar-label {
    @apply transition-opacity delay-100 duration-150 motion-reduce:transition-none;

    @variant sidebar-collapsed {
      @apply pointer-events-none absolute opacity-0 transition-none;
    }
  }

  /* In the collapsed sidebar the label of a link doubles as its tooltip. */
  :is(a, button) > .sidebar-label {
    @variant sidebar-collapsed {
      @apply top-1/2 left-[calc(100%+1.5rem)] z-50 -translate-y-1/2 rounded-md bg-zinc-900 px-2 py-1 text-xs/5 font-medium text-white shadow-sm;
    }
  }

  :is(a, button):is(:hover, :focus-visible) > .sidebar-label {
    @variant sidebar-collapsed {
      @apply opacity-100;
    }
  }

  /* --- Full-width data table -------------------------------------------
     Lives in a scroll container (#…-scroll) that owns both scroll axes. The header and
     the first column are sticky; borders sit on the cells (border-separate) because
     collapsed borders do not travel with sticky cells. */

  .table {
    @apply min-w-full border-separate border-spacing-0 tabular-nums;
  }

  .table thead {
    @apply sticky top-0 z-10;
  }

  .table th {
    @apply border-b border-gray-300 bg-white px-3 py-3 text-left text-sm font-medium text-gray-900;
  }

  .table th.right-aligned {
    @apply text-right;
  }

  .table th:first-child {
    @apply pl-4 pr-3 sm:pl-6 lg:pl-8;
  }

  .table th:last-child {
    @apply pr-4 sm:pr-6 lg:pr-8;
  }

  .table th a {
    @apply flex items-center gap-1;
  }

  .table th.right-aligned a {
    @apply justify-end;
  }

  .table tbody td {
    @apply border-b border-gray-200 bg-white;
  }

  /* Above a .table-footer the footer's top border already closes the table. */
  :has(> .table-footer) .table tbody tr:last-child td {
    @apply border-b-0;
  }

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

  /* The record the user opened last from this table (see LastClicked concern). */
  .table tbody tr[data-last-clicked] td {
    @apply bg-primary-50;
  }

  /* Row backgrounds must be opaque: sticky cells would show the scrolled-under columns
     through a translucent one. This is primary-100 at 60% over white, pre-mixed. */
  .table tbody tr[data-last-clicked]:hover td {
    @apply bg-[color-mix(in_oklab,var(--color-primary-100)_60%,white)];
  }

  /* Sticky first column; the header cell sits above both axes. */
  .table th:first-child,
  .table tbody td:first-child {
    @apply sticky left-0 z-[1];
  }

  .table th:first-child {
    @apply z-20;
  }

  .table tr td > a,
  .table tr td > span {
    @apply block w-full px-3 py-3 text-sm text-gray-500;
  }

  /* First and last column mirror the toolbar's horizontal padding. */
  .table tr td:first-child > a,
  .table tr td:first-child > span {
    @apply pl-4 sm:pl-6 lg:pl-8;
  }

  .table tr td:last-child > a,
  .table tr td:last-child > span {
    @apply pr-4 sm:pr-6 lg:pr-8;
  }

  /* Narrow row-actions column (the "…" menu); opt in with class="actions" on th and td. */
  .table th.actions {
    @apply w-14;
  }

  .table tbody td.actions {
    @apply w-1 py-2 pr-4 text-gray-500 sm:pr-6 lg:pr-8;
  }

  /* Fixed layout prevents columns from jumping when sorting/filtering. */
  .table-fixed {
    table-layout: fixed;
    width: 100%;
  }

  .table-fixed th,
  .table-fixed td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .table-fixed td > a,
  .table-fixed td > span {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .table-toolbar {
    @apply flex min-h-14 items-center border-t border-b border-gray-200 bg-gray-50 px-4 py-2 sm:px-6 lg:px-8;
  }

  .table-toolbar > div {
    @apply mr-6 text-sm font-medium whitespace-nowrap text-gray-700;
  }

  .table-toolbar > .table-toolbar-right {
    @apply mr-0 ml-auto flex items-center gap-3;
  }

  /* Pagination bar under a full-height table. The admin layout drops its bottom
     padding when a page contains one, so the table closes flush with the window. */
  .table-footer {
    @apply flex shrink-0 flex-wrap items-center gap-4 border-t border-gray-200 px-4 py-3 sm:px-6 lg:px-8;
  }

  .table-footer > .table-footer-right {
    @apply ml-auto flex items-center gap-4 text-sm text-gray-500;
  }

  /* --- Compact boxed table --------------------------------------------- */

  .table-boxed {
    @apply min-w-full divide-y divide-gray-300;

    & thead {
      @apply bg-gray-50;
    }

    & th {
      @apply px-3 py-3.5 text-left text-sm font-semibold whitespace-nowrap text-gray-900;
    }

    & th a {
      @apply flex items-center gap-1;
    }

    & th:first-child {
      @apply py-3.5 pl-4 pr-3 sm:pl-6;
    }

    & tbody {
      @apply divide-y divide-gray-200 bg-white;

      & tr {
        @apply text-sm text-gray-700 hover:bg-gray-50;
      }
    }

    & tr td > a,
    & tr td > span {
      @apply block w-full px-3 py-3 whitespace-nowrap;
    }

    & tr td:first-child > a,
    & tr td:first-child > span {
      @apply block py-3 pl-4 pr-3 sm:pl-6;
    }
  }

  /* --- Dialog / slideover ------------------------------------------------ */

  .slideover {
    @apply m-0 ml-auto h-dvh max-h-dvh w-full transform bg-white text-left transition duration-500 ease-in-out sm:max-w-lg backdrop:bg-black/50 backdrop:duration-500 backdrop:ease-in-out;
  }

  /* Title bar for simple slideovers that only have a title (e.g. filters). It bleeds out of
     the content padding and is as tall as the admin top bar (h-16), so its bottom border
     continues the line of the top bar and the navigation; a border a few pixels off that
     line would look like a mistake. Detail slideovers with a taller header (title, subline,
     tabs, see admin/orders/_header) do not use it and deliberately do not align. */
  .dialog-header {
    @apply -mx-4 -mt-5 flex h-16 items-center border-b border-gray-200 px-4 pr-16 sm:-mx-6 sm:-mt-6 sm:px-6 sm:pr-16;
  }

  .dialog {
    @apply rounded-lg bg-white text-left shadow-xl sm:w-full sm:max-w-lg backdrop:bg-black/50;
  }

  /* --- Pagy ------------------------------------------------------------- */

  .pagy.series-nav {
    @apply flex items-center justify-start gap-1;

    & a,
    & [role="link"] {
      @apply inline-flex h-8 min-w-8 items-center justify-center rounded-md px-2 text-sm font-medium transition-colors;
    }

    & a {
      @apply text-gray-700 hover:bg-gray-100 focus:ring-2 focus:ring-primary-500 focus:ring-offset-1 focus:outline-hidden;
    }

    & a[aria-current="page"],
    & [role="link"][aria-current="page"] {
      @apply pointer-events-none bg-primary-600 text-white;
    }

    & [aria-disabled="true"]:not([aria-current="page"]) {
      @apply pointer-events-none text-gray-300;
    }
  }
}
