/* Brand layer over daisyUI.
 *
 * daisyUI's own theme variables are OKLCH triplets, which would mean converting
 * Organization.branding hex values at request time. Instead the palette lands as
 * --cc-* custom properties (see core/context_processors.py) and these few classes
 * consume them, so rebranding stays a settings change. Swapping this for a real
 * compiled daisyUI theme is noted in docs/MVP-NOTES.md.
 */

/* The app is light-only, so say so: native <select> popups, scrollbars and the
 * calendar button on a date input follow the *used* color scheme rather than
 * our palette, and without this they follow the OS when the OS is dark.
 *
 * daisyUI's [data-theme=light] already declares the same thing, so this is
 * belt and braces against the CDN stylesheet not loading — it is not a fix for
 * anything currently broken. It specifically does NOT light up a <datalist>
 * popup: measured dark in both Chrome and Firefox with this set on :root and
 * on the input itself. See docs/adr/0017-dispensing-details.md.
 */
:root {
  color-scheme: light;
}

.btn-brand {
  background-color: var(--cc-primary);
  border-color: var(--cc-primary);
  color: #fff;
}

.btn-brand:hover {
  background-color: var(--cc-primary-dark);
  border-color: var(--cc-primary-dark);
}

.btn-brand-ghost {
  color: var(--cc-primary);
  border-color: var(--cc-primary);
  background-color: transparent;
}

.card-surface {
  background-color: var(--cc-surface);
  border: 1px solid rgb(0 0 0 / 0.06);
}

.text-muted {
  color: var(--cc-text-muted);
}

/* HTMX indicators: hidden by default, shown only while a request is in flight. */
.htmx-indicator {
  opacity: 0;
  transition: opacity 150ms ease-in;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

/* Tables become cards on a phone.
 *
 * A list that scrolls sideways is a list you cannot read: the column that
 * matters is always the one off-screen, and on a touch device the horizontal
 * scroll fights the vertical one. Below the `sm` breakpoint every `.table-cards`
 * row becomes a stacked card whose cells carry their own heading, taken from
 * `data-label` on the `td` — so the header row can be dropped without the
 * numbers losing their meaning.
 *
 * A `td` with no `data-label` (an actions cell, a badge) renders full width with
 * no heading, which is what those want anyway.
 *
 * Two opt-in annotations make the card compact, because one labelled row per
 * column is honest but enormous — a five-column patient list gave a card five
 * rows tall and fitted one and a half patients on a phone screen, which is a
 * list you cannot skim:
 *
 *   data-card="title"  the identifying cell. A heading: full width, no label,
 *                      because "Name: Rahima Rahman" is a label nobody needed.
 *   data-card="meta"   secondary cells. Condensed onto a shared line, label
 *                      dropped, muted.
 *
 * Anything unannotated keeps the labelled full-width row, which is the right
 * default: it is what a number needs. "89.50" with no label is a mystery, so
 * money and counts stay labelled and only the self-evident things — a code, an
 * age, a phone number, a date — become meta.
 */
@media (max-width: 639px) {
  /* `table.` on the element: daisyUI ships `table.table { display: table }`,
   * which outranks a bare class and left the element a table with block rows. */
  table.table-cards,
  table.table-cards tbody,
  table.table-cards td {
    display: block;
    width: 100%;
  }

  table.table-cards thead {
    display: none;
  }

  /* The row is a wrapping flex container so that meta cells can share a line
   * while everything else spans it. `column-gap` rather than a separator glyph
   * on purpose: an empty cell is set to `display: none` below, and a `::before`
   * separator would still render against its hidden neighbour — a stray
   * middot leading a line, for a cell that had nothing to say. */
  table.table-cards tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 0.75rem;
    background-color: var(--cc-surface);
    border: 1px solid rgb(0 0 0 / 0.08);
    border-radius: 0.75rem;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.75rem;
  }

  table.table-cards td {
    /* Full width unless something opts out; this is what keeps every
     * unannotated table rendering exactly as it did before. */
    flex: 0 0 100%;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.3rem 0;
    border: 0;
    text-align: right;
    white-space: normal;
  }

  table.table-cards td[data-label]::before {
    content: attr(data-label);
    color: var(--cc-text-muted);
    font-size: 0.75rem;
    text-align: left;
    flex: 0 0 auto;
  }

  /* The card has three tiers, and `order` puts the cells in them regardless of
   * which column they happen to be in: title, then every meta, then the
   * labelled rows. Reordering the `td`s in the template instead would drag the
   * desktop table's column order along with it, and that order is fine — a
   * patient list leads with the code, an invoice list with the number, and the
   * status badge sits last where a wide table wants it.
   *
   * Without the tiers a meta simply keeps its DOM position, so the invoice
   * status badge — the last column — landed on a line of its own beneath the
   * balance, inline but alone, which is the widest possible way to say
   * "Unpaid". */
  table.table-cards td[data-card='title'] {
    order: -2;
    display: block;
    text-align: left;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    padding: 0.1rem 0 0.2rem;
  }

  /* Secondary cells: inline, small, muted, no label. `flex: 0 1 auto` lets
   * several share a line and wrap to the next when they run out of room. */
  table.table-cards td[data-card='meta'] {
    order: -1;
    flex: 0 1 auto;
    width: auto;
    display: block;
    text-align: left;
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--cc-text-muted);
    padding: 0 0 0.1rem;
  }

  /* Both annotations drop the heading — that is the point of them. */
  table.table-cards td[data-card='title'][data-label]::before,
  table.table-cards td[data-card='meta'][data-label]::before {
    content: none;
  }

  /* An empty cell is a column that had nothing to say for this row. */
  table.table-cards td:empty {
    display: none;
  }
}

/* Toasts wrap instead of running off the screen.
 *
 * daisyUI's `.toast` is `white-space: nowrap` **and** `min-width: fit-content`,
 * anchored to the right edge. A message wider than the viewport therefore grows
 * *leftwards* off the screen and its first words — which is where the subject of
 * the sentence lives — cannot be read at all. On a phone that is most messages:
 * anything naming a file, a patient, or a medicine clears 375px easily.
 *
 * All three declarations are needed, and the order they were discovered in
 * matters to anyone changing this:
 *
 *   - `min-width: 0` first. `min-width` beats `max-width` in the cascade, so
 *     while `fit-content` stands, any cap added here is silently ignored. An
 *     earlier attempt at this fix set only a max-width and did nothing at all.
 *   - `white-space: normal`, or there is no break opportunity for a cap to use.
 *   - the cap itself. `28rem` keeps a long message readable on a wide screen
 *     rather than letting one sentence span a 1440px monitor; the `calc` is what
 *     holds it inside a phone.
 *
 * Width is still shrink-to-fit, so a short toast stays short — only the long
 * ones are affected.
 */
#toasts {
  min-width: 0;
  white-space: normal;
  max-width: min(28rem, calc(100vw - 2rem));
}

/* Modals fill the phone.
 *
 * A dialog that leaves a margin of backdrop on every side is a desktop dialog
 * shrunk down: it wastes the width the form needs, and the inputs inside end up
 * narrower than the screen can afford. Below `sm` the box takes the viewport,
 * scrolls its own body, and keeps its actions reachable above the bottom nav.
 */
@media (max-width: 639px) {
  /* The dialog itself carries padding that keeps the box off the edges, so it
   * has to go too — otherwise the box is 86% of the screen however wide it is
   * told to be. `.modal .modal-box` to outrank daisyUI's own `.modal-box`. */
  .modal {
    padding: 0;
  }

  .modal .modal-box {
    max-width: 100vw;
    width: 100vw;
    max-height: 100dvh;
    height: 100dvh;
    border-radius: 0;
    display: flex;
    flex-direction: column;
    padding-bottom: max(1.5rem, env(safe-area-inset-bottom));
  }

  /* The action row stays put while the fields above it scroll, so "Save" is
   * never below the fold on a short screen with a keyboard open. */
  .modal .modal-box > .modal-action {
    margin-top: auto;
    padding-top: 1rem;
  }
}

/* Fingers, not mice. Below `sm` the small button variants keep their compact
 * look but grow to a 44px touch target, which is the smallest thing a thumb
 * hits reliably. */
@media (max-width: 639px) {
  .btn-sm,
  .select-sm,
  .input-sm {
    min-height: 2.75rem;
    height: 2.75rem;
  }

  /* `btn-xs` is a table-row action — Edit, Deactivate, Batches. At 23px it is a
   * mouse target; in a stacked card it is a thumb target. It keeps its small
   * text and grows only its box. */
  .btn-xs {
    min-height: 2.75rem;
    height: 2.75rem;
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }

  /* Five destinations in 375px, which is 75px each before padding.
   *
   * The labels used to be truncated with an ellipsis, which is the wrong answer
   * twice over: "Appointment…" is not a word, and the longest label is the one
   * a receptionist needs most. An icon carries the recognition instead, so the
   * text can be small enough to fit whole — 0.625rem renders "Appointments" at
   * about 62px, inside the ~67px a cell has after padding.
   *
   * `overflow: hidden` stays as a backstop: the labels come from the
   * terminology map, so a clinic can rename Appointments to something longer,
   * and clipping is a better failure than a nav bar pushed sideways. */
  .btm-nav > * {
    padding-left: 0.125rem;
    padding-right: 0.125rem;
    min-width: 0;
    gap: 0.1rem;
  }

  .btm-nav .btm-nav-label {
    font-size: 0.625rem;
    line-height: 1.15;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
  }
}

/* The nav icons are sized outside the phone media query: the bar itself is
 * `lg:hidden`, so it is on show from 640 to 1023px too, where the labels are
 * roomy but the icons still need a size. */
@media (max-width: 1023px) {
  .btm-nav .btm-nav-icon {
    width: 1.375rem;
    height: 1.375rem;
    flex: 0 0 auto;
  }

  /* daisyUI centres the label on a bar with no icon; with one, the pair reads
   * better pushed together and lifted slightly off the home indicator. */
  .btm-nav > * {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
  }

  /* Menu rows: the sidebar links and the Log out item in the user dropdown.
   * daisyUI sizes these from text, which left Log out a 34px strip. */
  .menu li > a,
  .menu li > button {
    min-height: 2.75rem;
    display: flex;
    align-items: center;
  }
}

/* Calm and clinical: no bounce, no slide. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Date pickers — see static/js/date-picker.js.
 *
 * `static: true`, which the instances inside a <dialog> need because the top
 * layer would otherwise hide the calendar, wraps the input in
 * .flatpickr-wrapper. flatpickr ships that wrapper as inline-block, and the
 * wrapper becomes the grid or flex item in the input's place — so a field the
 * template sized w-full collapses to its content width without this.
 */
.flatpickr-wrapper {
  display: block;
}

/* The calendar is the clinic's colour, not flatpickr's blue. */
.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
  background: var(--cc-primary);
  border-color: var(--cc-primary);
}

.flatpickr-day.today {
  border-color: var(--cc-primary);
}
