@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  /* Preflight already emits this selector without !important, but utilities
     load in a later @layer and win on source order (e.g. .flex beats `hidden`
     silently). This !important is what makes `hidden` win — not a Preflight gap. */
  [hidden]:where(:not([hidden="until-found"])) {
    display: none !important;
  }
}

@layer components {
  /* Main nav */
  body > div > aside > nav h6 {
    @apply uppercase font-bold text-sm px-2 text-gray-500 cursor-default;
  }

  body > div > aside > nav ul {
    @apply space-y-0.5;
  }

  body > div > aside > nav ul li a {
    @apply w-full px-2 py-1 flex items-center gap-1 border border-transparent hover:bg-gray-200 rounded-lg text-gray-600;
  }

  body > div > aside > nav ul li svg {
    @apply size-4;
  }

  body > div > aside > nav ul li a:not(.btn--prescribe):hover {
    @apply text-black;
  }

  body > div > aside > nav ul li a:not(.btn--prescribe):hover svg {
    @apply !text-black;
  }

  body > div > aside > nav ul li a:not(.btn--prescribe):hover svg {
    @apply text-black;
  }

  body > div > aside > nav ul:not(:last-child) {
    @apply !mb-6;
  }

  /* Primary CTA gradient for the cart Create Order nav button.
     background-size: 110% with centered position pushes the two outer
     gradient stops 5% offscreen on each side, so the visible button shows
     the brand colors at its quarter/three-quarter marks rather than fading
     to lighter shoulders at the rounded edges. */
  .btn--prescribe-cta {
    background-image: linear-gradient(to right, #5C44E0, #7B61FF 25%, #22D3EE 75%, #1AB9D2);
    background-size: 110% 100%;
    background-position: center;
  }

  /* Table styles */
  table.styled {
    @apply table-auto w-full;
  }

  table.styled th,
  table.styled td {
    @apply px-1.5 py-1 whitespace-nowrap;
  }

  table.styled thead th {
    @apply text-left font-medium text-sm text-gray-700 uppercase border-b border-b-gray-400;
  }

  table.styled tbody tr {
    @apply odd:bg-white border-b border-b-gray-300;
  }

  /* GH-2048: each catalog row is its own tbody, so every main row is :first-child and the odd:bg-white
     stripe above would paint them all white. Stripe by tbody instead; an open band follows its row. */
  table.styled tbody.catalog-row > tr {
    @apply bg-transparent;
  }

  table.styled tbody.catalog-row:nth-of-type(odd) > tr {
    @apply bg-white;
  }

  /* Margin-warning highlight must beat the odd:bg-white zebra stripe above,
     which otherwise wins on odd rows by specificity. Declared after the stripe
     rule with matching specificity so it takes precedence on both parities. */
  table.styled tbody tr.margin-issue {
    @apply bg-red-50;
  }

  table.styled.styled--divided-cols tr th,
  table.styled.styled--divided-cols tr td, {
    @apply odd:bg-gray-200/80;
  }

  /* Admin › Routes › Assign routes (CU-86bcyf3ye). Written as table rules so each of the page's thousands of rows and
     checkboxes carries no classes of its own. Sticky headings, the Variant column held in view while the route columns
     scroll sideways, inactive variants muted, a pending change's cell highlighted, a row that failed to save in red. */
  table.route-assign thead th {
    @apply sticky top-0 z-10 bg-white align-bottom;
  }
  table.route-assign thead th:nth-child(2) {
    @apply left-0 z-20;
  }
  table.route-assign tbody td:nth-child(2) {
    @apply sticky left-0 z-[5] bg-inherit shadow-[1px_0_0_theme(colors.gray.200)] whitespace-normal min-w-[11rem] sm:min-w-[16rem];
  }
  table.route-assign tbody td:first-child {
    @apply whitespace-normal min-w-[10rem];
  }
  table.route-assign tbody tr {
    @apply bg-white;
  }
  table.styled.route-assign tbody td:has(> input) {
    @apply text-center p-0;
  }
  table.route-assign tbody td > input {
    @apply m-2 rounded border-gray-300 cursor-pointer;
  }
  table.route-assign tbody tr.ra-inactive {
    @apply bg-gray-100 text-gray-500;
  }
  table.route-assign .ra-badge {
    @apply ml-1 inline-block rounded bg-gray-300 px-1.5 py-0.5 text-xs font-medium text-gray-700;
  }
  table.route-assign tbody tr.ra-changed td:nth-child(2) {
    @apply bg-amber-50;
  }
  table.route-assign tbody .ra-cell-changed {
    @apply bg-amber-200;
  }
  table.route-assign tbody tr.ra-failed,
  table.route-assign tbody tr.ra-failed td:nth-child(2) {
    @apply bg-red-50;
  }

  table.styled tbody tr.totals {
    @apply border-none bg-gray-200;
  }

  table.styled tbody tr.grand-totals {
    @apply border-b-0 border-t border-t-gray-400 bg-gray-300;
  }

  /* Main entity column */
  a.main-entity,
  table.styled tbody td:first-child a {
    @apply font-bold underline text-gray-700;
  }

  /* Actions column */
  table.styled th:last-child,
  table.styled tbody td:last-child,
  table.styled tfoot td:last-child {
    @apply text-right;
  }

  /* Form styles */
  .btn {
    @apply bg-black text-white px-1.5 py-1 text-sm sm:text-base sm:px-3 sm:py-2 inline-block cursor-pointer rounded-lg font-medium whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed;
  }

  .btn.btn--sm {
    @apply text-sm px-2 py-1;
  }

  .btn.btn--tiny {
    @apply text-xs font-medium px-1.5 py-0.5;
  }

  .btn.btn--lg {
    @apply text-lg px-4 py-3;
  }

  /* CU-86bbuda4t (decision 27): #7C3AED provides 5.7:1 contrast with white text,
     clearing the 4.5:1 minimum for accessibility. App-wide: all 68 uses. */
  .btn.btn--alt {
    @apply bg-[#7C3AED] text-white;
  }

  .btn.btn--alt2 {
    @apply bg-white text-black ring ring-black;
  }

  .btn.btn--danger {
    @apply bg-red-500 text-white;
  }

  /* Outlined white pill: View, Cancel and the other quiet choices beside a black button. */
  .btn.btn--outline {
    @apply bg-white text-gray-900 border border-gray-300 hover:border-gray-500 hover:bg-gray-50;
  }

  /* Red-tinted pill: a danger action beside a black button, such as Unlock all. */
  .btn.btn--danger-tint {
    @apply bg-red-100 text-red-700 hover:bg-red-200;
  }

  form.styled {
    @apply space-y-3 w-full md:w-2/3 2xl:w-1/2;
  }

  form.styled hr {
    @apply border-2 border-gray-300;
  }

  form.styled input[type="submit"] {
    @apply btn;
  }

  form.styled fieldset {
    @apply flex flex-col gap-1;
  }

  form.styled fieldset.checkbox {
    @apply !flex-row;
  }

  form.styled fieldset label {
    @apply text-sm font-medium uppercase tracking-wide text-gray-700;
  }

  form.styled fieldset input,
  form.styled fieldset textarea,
  form.styled fieldset select,
  input.styled,
  select.styled,
  .styled-input {
    @apply px-3 py-2 border rounded-lg bg-white;
  }

  form.styled fieldset .faux-disabled {
    @apply select-none cursor-not-allowed opacity-50 pointer-events-none;
  }

  /* Filter card (admin invoices): a custom dropdown button and a nice-select
     drawn at the same height, border and type as each other. */
  .filter-card .filter-control,
  .filter-card .nice-select {
    @apply h-10 px-3 bg-white border border-gray-300 rounded-lg text-sm leading-10 hover:border-gray-400;
  }

  .filter-card .nice-select .nice-select-dropdown {
    @apply rounded-lg shadow-lg;
  }

  .filter-card .nice-select .option {
    @apply text-sm leading-8 min-h-8;
  }

  /* Match nice-select to other form inputs */
  form.styled .nice-select {
    @apply text-base h-auto py-2 leading-normal;
  }

  /* FUTURE: editor/toolbar too wide */
  form.styled .trix-content {
    @apply !bg-white !rounded-lg;
  }

  /* Overrides since Trix gets messed up by TW */
  .trix-content ul {
    @apply list-disc;
  }

  .trix-content ol {
    @apply list-decimal;
  }

  form.styled .field_with_errors:not(:has(.trix-content)) {
    @apply flex w-full *:grow;
  }

  form.styled .field_with_errors label {
    @apply text-red-600;
  }

  form.styled .field_with_errors [id] {
    @apply ring-2 ring-red-400;
  }

  /* Main layout frame */
  body > div > main h1 {
    @apply text-xl sm:text-3xl font-bold;
  }

  main > header {
    @apply sm:flex items-center gap-2 justify-between mb-4;
  }

  main > header h1 span:not(:last-child) {
    @apply text-gray-600 after:content-['/'] after:ml-1 after:sm:ml-2 after:font-light after:text-gray-400;
  }

  main > header h1 span:not(:last-child) a {
    @apply underline decoration-gray-200 hover:decoration-gray-400;
  }

  main > header h1 span:last-child {
    @apply text-blue-600;
  }

  /* Helpers */
  .callout {
    @apply bg-yellow-100 px-2 py-1 text-sm;
  }

  .callout-box {
    @apply bg-yellow-100 text-lg ring-2 ring-yellow-300 px-3 py-4 my-3 w-full xl:w-1/2 text-center space-y-2 rounded-lg;
  }

  .callout-box.callout-box--serious {
    @apply bg-red-100 ring-red-300;
  }

  .callout-box h6 {
    @apply font-medium text-xl;
  }

  .pill {
    @apply text-xs uppercase font-medium rounded-full bg-gray-200 px-2 py-1 cursor-default whitespace-nowrap;
  }

  .pill.pill--selected {
    @apply bg-black text-white;
  }

  /* CU-86bc9kt4e (pricing per 30 g, frame C, revision 5): the amount a price covers, after it, as in
     "$59.00 per 30 g". Quieter than the price, which keeps its own weight and color. It never breaks inside, so
     a narrow cell wraps it whole under the price. */
  .unit {
    @apply font-normal text-gray-500 whitespace-nowrap;
    font-size: 0.85em;
  }

  /* One-shot "your change landed here" flash on the card a turbo stream just
     saved — the visual receipt that replaces a toast. */
  .flash-highlight {
    animation: flash-highlight 1.6s ease-out;
  }

  @keyframes flash-highlight {
    from { background-color: #fef9c3; } /* yellow-100 */
    to   { background-color: #ffffff; }
  }

  /* Lists of stuff */
  dl.styled {
    @apply md:flex md:flex-wrap md:w-2/3 items-center *:px-2 *:py-1;
  }

  dl.styled dd:empty::after {
    content: 'Not provided';
    color: rgb(251, 191, 36); /* amber-400 */
    font-weight: bold;
  }

  dl.styled dt {
    @apply font-bold text-lg w-1/3 md:text-right;
  }

  dl.styled dd {
    @apply text-base w-2/3;
  }

  /* Popup menus */
  ul.menu {
    @apply md:absolute bg-white text-black px-1 py-2 z-[99] shadow-lg rounded-lg md:min-w-[18rem] border border-b-gray-300;
  }

  ul.menu li.section {
    @apply text-sm uppercase text-gray-500 font-medium tracking-wide select-none px-2;
  }

  ul.menu li > a {
    @apply block hover:bg-gray-100 rounded px-2 py-1;
  }

  ul.menu li .active {
    @apply font-bold hover:bg-transparent cursor-default;
  }

  /* Filter bars */
  .filter-bar {
    @apply flex gap-1 items-center justify-between mb-2;
  }

  /* TODO: search form -> make smaller */

  .filter-bar .filters {
    @apply flex items-center gap-1 whitespace-nowrap;
  }

  /* CU-86bbuda4t (decision 27): the selected pill takes the same darkened purple as .btn.btn--alt, for
     the same reason: it is white text on it. */
  .filter-bar .filters a {
    @apply block uppercase font-medium text-xs sm:text-sm bg-gray-200/80 hover:bg-gray-300/80 rounded-full px-3 py-1 aria-selected:bg-[#7C3AED] aria-selected:text-white;
  }

  /* Chat Messages */
  .chat-message {
    @apply px-4 py-2;
  }

  .chat-message.chat-message--parent {
    @apply text-lg;
  }

  /* Toggle matrix (app/views/toggle_matrix, docs/toggle-matrix.md) */
  .toggle-matrix {
    @apply rounded-xl border border-gray-200 bg-white p-5 shadow-sm;
  }

  .toggle-matrix__toolbar {
    @apply mb-4 flex flex-wrap items-center gap-2;
  }

  .toggle-matrix__footer {
    @apply mt-3 flex items-center justify-between text-xs text-gray-600;
  }

  .toggle-matrix__scroll {
    @apply overflow-x-auto rounded-lg border border-gray-200;
  }

  .toggle-matrix__table {
    @apply w-max min-w-full border-separate border-spacing-0 bg-white text-sm;
  }

  .toggle-matrix__table th,
  .toggle-matrix__table td {
    @apply border-b border-gray-200 px-3;
  }

  .toggle-matrix__table th {
    @apply text-left;
  }

  .toggle-matrix__table thead th {
    @apply bg-gray-50 font-semibold text-gray-700;
  }

  .toggle-matrix__table tbody tr:last-child > * {
    @apply border-b-0;
  }

  /* The first two columns stay put while the group columns scroll. */
  .matrix-sticky-1 {
    @apply sticky left-0 z-20 w-[13rem] min-w-[13rem] bg-inherit;
  }

  .matrix-sticky-2 {
    @apply sticky left-[13rem] z-20 w-[10rem] min-w-[10rem] bg-inherit shadow-[1px_0_0_theme(colors.gray.200)];
  }

  .matrix-corner {
    @apply align-bottom text-xs uppercase tracking-wide;
  }

  .matrix-group-start {
    @apply border-l border-l-gray-200;
  }

  .matrix-group-head {
    @apply py-2 text-sm normal-case text-gray-900;
  }

  .matrix-chevron {
    @apply -ml-1 inline-flex items-center gap-1.5 rounded px-1 font-semibold hover:bg-gray-200;
  }

  .matrix-chevron svg {
    @apply transition-transform;
  }

  .matrix-chevron[aria-expanded="true"] svg {
    @apply rotate-90;
  }

  .matrix-count {
    @apply ml-2 text-xs font-normal text-gray-600 underline decoration-dotted underline-offset-2 hover:text-blue-600;
  }

  .matrix-item-head {
    @apply w-32 min-w-32 py-3 align-bottom text-xs uppercase tracking-wide;
  }

  .matrix-select-all {
    @apply mt-2 flex cursor-pointer items-center gap-1.5 text-sm font-normal normal-case tracking-normal text-gray-700;
  }

  .matrix-row {
    @apply bg-white hover:bg-gray-50;
  }

  .matrix-row > * {
    @apply py-2.5 font-normal text-gray-700;
  }

  .matrix-person {
    @apply flex items-center gap-2.5 normal-case tracking-normal;
  }

  .matrix-avatar {
    @apply flex size-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-xs font-semibold text-blue-800;
  }

  .matrix-person__name {
    @apply block whitespace-nowrap text-sm font-semibold text-gray-900;
  }

  .matrix-person__note {
    @apply block text-xs text-gray-600;
  }

  .matrix-cell {
    @apply w-32 min-w-32 whitespace-nowrap text-center;
  }

  .matrix-check {
    @apply size-5 cursor-pointer align-middle accent-blue-600 disabled:cursor-not-allowed disabled:opacity-60;
  }

  .matrix-caption {
    @apply ml-1.5 rounded px-1.5 py-1 align-middle text-xs text-gray-600 underline decoration-dotted underline-offset-2 hover:bg-blue-50 hover:text-blue-700;
  }

  .matrix-search {
    @apply flex w-72 items-center rounded-lg border border-gray-300 bg-white px-3 focus-within:ring-2 focus-within:ring-blue-500;
  }

  .matrix-search input {
    @apply w-full border-0 bg-transparent px-2 py-2 text-sm outline-none focus:ring-0;
  }

  .matrix-select {
    @apply rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm;
  }

  .matrix-button {
    @apply rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm font-medium hover:bg-gray-100;
  }

  .matrix-popover {
    @apply fixed z-50 w-72 rounded-xl border border-gray-300 bg-white text-sm shadow-xl;
  }

  .matrix-popover__item {
    @apply flex cursor-pointer items-start gap-2.5 rounded-md px-2 py-1.5 hover:bg-gray-50;
  }
}

/* Pagy - FIXME: un-nest, move to components */
.pagy {
  @apply flex items-center justify-center my-3 space-x-2;

  a {
    @apply btn btn--sm bg-gray-200 text-black hover:bg-black hover:text-white;
  }

  a[aria-disabled="true"] {
    @apply cursor-default bg-gray-50 text-black font-bold;
  }
}
