/* The widgets Django supplies, dressed to match the rest of Sindisa.

   Both halves of the application load this file, because both use those
   widgets: the date picker and the searchable select appear on /animals/…/edit/
   exactly as they do on /admin/core/animal/…/change/.

   It carries the mapping of Django's own CSS variables onto our palette as
   well. admin/css/base.css, where Django defines them, is not loaded, but
   widgets.css and the select2 theme still read them.

   The selector list wins in every theme: Django sets its own dark values on
   `html[data-theme="dark"]`, which would otherwise out-specify a bare :root.
   Our tokens already switch themselves, so one mapping serves light, dark
   and auto. */

:root,
html[data-theme] {
  --primary: var(--accent);
  --secondary: var(--accent);
  --primary-fg: #fff;

  --body-fg: var(--ink);
  --body-bg: var(--paper);
  --body-quiet-color: var(--ink-faint);
  --body-medium-color: var(--ink-soft);
  --body-loud-color: var(--ink);

  /* The site's navbar is a pale card with teal type and a teal rule; the
     admin header is the same thing across the top. */
  --header-bg: var(--nav-bg);
  --header-color: var(--nav-fg);
  --header-link-color: var(--nav-fg);
  --header-branding-color: var(--nav-fg);

  --breadcrumbs-bg: var(--accent-soft);
  --breadcrumbs-fg: var(--ink-soft);
  --breadcrumbs-link-fg: var(--accent-strong);

  --link-fg: var(--accent-strong);
  --link-hover-color: var(--accent-strong);
  --link-selected-fg: var(--accent-strong);

  --hairline-color: var(--line-soft);
  --border-color: var(--line);

  --error-fg: var(--bad);

  --message-info-bg: var(--accent-soft);
  --message-success-bg: var(--accent-soft);
  --message-warning-bg: var(--warn-soft);
  --message-error-bg: var(--bad-soft);
  --message-debug-bg: var(--line-soft);

  --darkened-bg: var(--accent-soft);
  --selected-bg: var(--line-soft);
  --selected-row: var(--warn-soft);

  --button-fg: #fff;
  --button-bg: var(--accent);
  --button-hover-bg: var(--accent-strong);
  --default-button-bg: var(--accent-strong);
  --default-button-hover-bg: var(--accent);
  --close-button-bg: var(--ink-faint);
  --close-button-hover-bg: var(--ink-soft);
  --delete-button-bg: var(--bad);
  --delete-button-hover-bg: var(--bad);

  --object-tools-fg: #fff;
  --object-tools-bg: var(--accent-strong);
  --object-tools-hover-bg: var(--accent);

  --font-family-primary: var(--sans);
  --font-family-monospace: var(--mono);
}

/* ---------- date and time fields ---------- */

/* Django splits a datetime into a date line and a time line, with a <br>
   between them; the site's fields are full width, which stretched each input
   across the form. Only their width needs answering — the arrangement is
   Django's and is left alone. */
p.datetime {
  font-weight: 400;
  color: var(--ink-soft);
}

/* A date alone comes wrapped in a paragraph too, whose own margins set it
   lower than the fields beside it and further from its label. */
p.date { margin: 0; }

.datetime input,
input.vDateField,
input.vTimeField {
  /* Django gives the date field size="10" and the time field size="8", so
     left at their intrinsic width the two lines do not line up under one
     another. A shared width fits the longer of the two ("YYYY-MM-DD") with
     room to spare and makes the pair look like one control instead of two
     differently sized ones. */
  width: 7rem;
  display: inline-block;
  margin-block-end: 0;
}

.datetime span,
.datetimeshortcuts,
.datetimeshortcuts a {
  font-size: var(--text-ui);
}

/* "Today" and "Now" beside a field are actions. The calendar's own
   Yesterday | Today | Tomorrow row is left as plain links. The script gives
   them role="button" and no class. */
.datetimeshortcuts a[role="button"] {
  display: inline-block;
  /* "Now" and "Today" are one word apart in length; without a shared width
     the two boxes beside a date and a time field visibly do not match. */
  min-width: 4.5rem;
  text-align: center;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-control);
  font-weight: 550;
  color: var(--accent);
  background: transparent;
  text-decoration: none;
}

.datetimeshortcuts a[role="button"]:hover {
  background: var(--accent-soft);
}

/* ---------- the date and time pickers ----------

   widgets.css draws these against the admin's old palette, with a couple of
   colours written in rather than taken from a variable. */

/* The month heading is a filled bar, so its text is the colour that goes on
   one — widgets.css hard-codes #333, which was legible on the old pale blue
   and is not on teal. */
.calendarbox,
.clockbox {
  /* The script gives the box class="calendarbox module", so it was picking up
     the 1rem of padding a module gets on a page. That inset the month bar from
     the top of the box while the arrows, positioned against the box, stayed
     where they were — which is how they came to sit above the bar rather than
     on it. These draw their own chrome, row by row. */
  padding: 0;

  /* The bar is given a known height so the arrows, which the script places
     against the top of the box and not inside the bar, can be centred on the
     month text exactly. */
  --month-bar: 2.25rem;

  /* Inline left/top positioning can push a picker beyond a narrow viewport.
     Centre it there; on larger screens it stays beside its field. */
  @media (max-width: 47.99rem) {
    position: fixed !important;
    inset: 0 !important;
    margin: auto !important;
    width: min(19em, calc(100vw - 2rem)) !important;
    height: fit-content;
    max-height: calc(100dvh - 2rem);
    overflow: auto;
  }
}

.calendar caption,
.calendarbox h2,
.clockbox h2 {
  background: var(--accent);
  color: var(--paper);
  font-size: var(--text-ui);
  height: var(--month-bar);
  line-height: var(--month-bar);
  padding: 0;
}

/* The month arrows are a sprite — a left chevron in its top half, a right one
   in its bottom — so they are masked rather than painted: that way they take a
   colour from the palette instead of shipping black.

   The offsets have to be set on the same selectors as the shorthand above,
   which out-specifies a bare .calendarnav-next and resets the position; that
   is what left both arrows pointing the same way. */
.calendarbox .calendarnav-previous,
.calendarbox .calendarnav-next {
  /* widgets.css pins them 8px from the top of the box; on the bar's centre
     line instead, level with the month they move. They are 15px square. */
  top: calc((var(--month-bar) - 15px) / 2);
  /* Sitting wholly on the teal bar, they take the colour its text takes. */
  background: var(--paper);
  mask: url("../../admin/img/calendar-icons.11b535e4a489.svg") no-repeat;
  -webkit-mask: url("../../admin/img/calendar-icons.11b535e4a489.svg") no-repeat;
}

.calendarbox .calendarnav-previous {
  mask-position: 0 0;
  -webkit-mask-position: 0 0;
}

.calendarbox .calendarnav-next {
  mask-position: 0 -15px;
  -webkit-mask-position: 0 -15px;
}

/* Yesterday | Today | Tomorrow, and Cancel: plain links, but the underline
   the rest of the site gives a link is noise in a box this small. */
.calendar-shortcuts a,
.calendar-cancel a {
  text-decoration: none;
}

.calendar-shortcuts {
  background: var(--card);
  color: var(--ink-soft);
  font-size: var(--text-small);
  line-height: 1.5;
  border-top: 1px solid var(--line);
}

/* Cancel is a secondary action, not a grey bar. */
.calendar-cancel {
  background: transparent;
  border-top: 1px solid var(--line);
  font-size: var(--text-small);

  & a {
    color: var(--accent);
    font-weight: 550;
  }
}

.calendar-cancel:focus,
.calendar-cancel:hover {
  background: var(--accent-soft);
}

/* ---------- select2 ---------- */

/* The autocomplete fields ship their own vendor theme. Matched to the fields
   beside them: same type size, same border, same radius. */
.select2-container {
  font-size: var(--text-ui);
}

select.admin-autocomplete {
  width: 100%;
  max-width: 32rem;
}

/* select2 measures the <select> it is replacing at the moment it
   initialises, and bakes what it finds into an inline style on the box it
   draws instead. A field whose row starts hidden — the kind-specific
   reference fields on the reminder form, before a kind names which one
   applies — measures as zero width and is written up as `width: auto`,
   which on an inline-block (what the box is) shrinks it to fit the
   placeholder text rather than filling the row. Showing the row later does
   not repeat the measurement, so the box stays tiny until the page is
   reloaded with that kind already chosen — which is exactly the bug this
   overrides. !important because the mistaken width is an inline style, and
   nothing lower in the cascade reaches over one of those. */
.select2-container--admin-autocomplete {
  width: 100% !important;
  max-width: 32rem;
}

/* The closed box is a <div> standing in for a <select>, so it is built like
   one: the same padding, border, radius, background and type size that
   `input, select, textarea` carry. The vendor draws it 28px tall and centres
   the value with a line-height to match, which is a size down from every other
   field on the form.

   The height is left to the padding, and the line-height reset along with it —
   sizing the box while a 30px line-height still stood is what knocked the
   value off centre when this was tried before. */
.select2-container--admin-autocomplete .select2-selection--single,
.select2-container--admin-autocomplete .select2-selection--multiple {
  height: auto;
  min-height: 0;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--paper);
}

.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
  color: var(--ink);
  font-size: var(--text-ui);
  line-height: normal;
  /* The arrow sits over the right-hand end, as a select's does. */
  padding: 0 1.25rem 0 0;
  /* Nothing chosen yet means nothing inside, and a box whose height is left
     to its padding then draws at half the height of every field beside it.
     One line of it is reserved whether or not there is anything to put on
     that line. */
  min-height: 1lh;
}

/* admin/css/autocomplete.css zeroes the padding again while the field is
   focused or open, four classes deep. Matched selector for selector, or the
   value jumps as the box opens. */
.select2-container--admin-autocomplete.select2-container--focus
  .select2-selection.select2-selection--single,
.select2-container--admin-autocomplete.select2-container--open
  .select2-selection.select2-selection--single,
.select2-container--admin-autocomplete.select2-container--focus
  .select2-selection.select2-selection--multiple,
.select2-container--admin-autocomplete.select2-container--open
  .select2-selection.select2-selection--multiple {
  min-height: 0;
  padding: 0.45rem 0.6rem;
}

/* The arrow a browser draws on a select, drawn by hand: the vendor's triangle,
   in the colour of quiet type, over the full height of the box. */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
  top: 0;
  right: 0.5rem;
  height: 100%;

  & b {
    border-top-color: var(--ink-soft);
  }
}

/* Several values in one box: the list is the box's own contents, so it holds
   no padding of its own, and each value is a small chip. Empty, it reserves
   its line the same way the single one above does. */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
  padding: 0;
  min-height: 1lh;
}

.select2-container--admin-autocomplete .select2-selection__choice {
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--ink);
  padding: 0 0.35rem;
}

.select2-container--admin-autocomplete.select2-container--focus .select2-selection,
.select2-container--admin-autocomplete.select2-container--open .select2-selection {
  border-color: var(--accent);
}

.select2-dropdown {
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--card);
  color: var(--ink);
  /* Flush against the box it drops from, as a native list is. */
  margin: 0;
}

/* A row keeps the vendor's height -- 6px above and below -- and is lined up
   with the fields sideways.

   The highlight is drawn on the row itself, so the row is held off the edges
   of the dropdown to leave a margin around it, the way a native list does.
   The padding gives back what the margin takes, so the text still sits
   0.6rem in -- level with the value in the closed box above it.

   The blank choice -- the one that clears the field -- has no text in it, so
   its row would otherwise be the padding alone: half the height of every row
   under it, and a list that reads as though it has been damaged. Box-sizing
   is border-box here, so the minimum counts the padding in. */
.select2-results__option {
  padding: 6px 0.25rem;
  margin-inline: 0.35rem;
  border-radius: 2px;
  min-height: calc(1lh + 12px);
}

.select2-results__options {
  margin: 0;
  padding: 0;
}

/* The search box inside the dropdown is a field like any other, so it takes
   the same padding, and the gap around it is the same measure again. */
.select2-search--dropdown {
  padding: 0.45rem 0.6rem;
}

.select2-search--dropdown .select2-search__field {
  font-size: var(--text-ui);
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
}

.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
  background: var(--accent);
  color: var(--paper);
}

/* ---------- the editor on a form's own prose ---------- */

/* The textarea is still the field; richtext.js hides it and puts these in
   front of it. Without that script the textarea is visible and somebody types
   the markup, which is what they were doing before it existed.

   Sized as every other field on the page is -- full width up to 32rem -- and
   not, as it was, running the whole width of the window while the boxes above
   and below it stopped a third of the way across. */
.richtext-editor {
  position: relative; /* the emoji list hangs off this */
  width: 100%;
  max-width: 32rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--card);
}

.richtext-toolbar {
  display: flex;
  align-items: center;
  gap: 0.1rem;
  /* Even room on all four sides, so the row of buttons sits in the band the
     way a field's contents sit in the field. */
  padding: 0.4rem;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  border-radius: var(--radius-control) var(--radius-control) 0 0;

  /* The box is the shape it holds and the border it grows on hover, and
     nothing besides: 20px around an 18px icon, where it began as a 30px
     square. Small for a finger, which these are not for -- this editor is a
     staff page, written at a desk. */
  & button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-control);
    background: none;
    color: var(--ink-soft);
    cursor: pointer;
  }
  & button:hover {
    background: var(--accent-soft);
    border-color: var(--line);
    color: var(--ink);
  }

  /* Turned off while the markup itself is on screen: these act on a
     selection in the box, and there is no box to select in. */
  & button:disabled {
    opacity: 0.35;
    cursor: default;
  }
  & button:disabled:hover {
    background: none;
    border-color: transparent;
    color: var(--ink-soft);
  }

  /* A button whose work is already done to the words the caret is in: bold
     inside bold, the list button inside that list. Drawn as though somebody
     were holding it down -- the hover's own colours, pushed in by a shadow
     inside the box -- rather than picked out in the accent, which made five
     buttons compete with the words being written. */
  & button[aria-pressed="true"] {
    background: var(--accent-soft);
    border-color: var(--line);
    color: var(--ink);
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 12%);
  }
}

/* The commands fall into three jobs -- wording, lists, links -- and a row of
   nine identical squares gives no hint which of them to look for. */
/* Under the toolbar and over the words, so opening it does not push the box
   somebody is typing in down the page. */
.richtext-emoji {
  position: absolute;
  z-index: 2;
  inset-inline-end: 0.25rem;
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 0.1rem;
  padding: 0.3rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  background: var(--card);
  box-shadow: 0 2px 8px rgb(0 0 0 / 12%);

  /* display: grid beats the browser's own [hidden] rule, which is what makes
     the closed panel visible and unclosable -- the script sets .hidden and
     nothing happens. Same reason .question[hidden] is spelled out. */
  &[hidden] {
    display: none;
  }

  & button {
    width: 1.6rem;
    height: 1.6rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-control);
    background: none;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
  }

  & button:hover {
    background: var(--accent-soft);
  }
}

@media (width < 32rem) {
  .richtext-emoji {
    grid-template-columns: repeat(6, 1fr);
  }
}

.richtext-separator {
  width: 1px;
  height: 1rem;
  margin-inline: 0.25rem;
  background: var(--line);
}

/* The field itself, which the script hides and shows again when somebody asks
   for the markup. It was never a copy of anything: it is what posts, and it is
   what is there when this script does not load at all -- so the code view is
   the plain textarea, dressed to sit in the box the toolbar is attached to.

   display is named here, so [hidden] has to be named too: a rule that gives an
   element a display beats the browser's own rule for the attribute, which is
   what once left the emoji panel open with nothing able to shut it. */
.richtext-editor > textarea {
  display: block;
  width: 100%;
  max-width: none;
  min-height: 6rem;
  height: 11rem;
  margin: 0;
  padding: 0.55rem 0.7rem;
  border: 0;
  border-radius: 0 0 var(--radius-control) var(--radius-control);
  background: var(--card);
  font-family: var(--mono);
  font-size: var(--text-small);

  &[hidden] {
    display: none;
  }
}

/* Resizable, and downwards only, exactly as a textarea is: the height that
   suits a one-line closing message is not the height that suits the adoption
   contract's terms, and the width is the form's to decide. */
.richtext-box {
  min-height: 6rem;
  height: 11rem;
  padding: 0.55rem 0.7rem;
  font-size: var(--text-ui);
  overflow-y: auto;
  resize: vertical;

  &:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

  & > *:first-child { margin-top: 0; }
  & p { margin: 0 0 0.7rem; }
  & h2, & h3 { font-size: var(--text-ui); font-weight: 600; margin: 0.8rem 0 0.3rem; }
  & ul, & ol { margin: 0 0 0.7rem; padding-inline-start: 1.4rem; }
  /* The admin's own forms.css sets `form .aligned ul li { list-style: none }`,
     and this box sits inside that fieldset -- so its markers were falling to
     that rule, at a specificity `.richtext-box li` alone cannot outrank.
     `.richtext-editor` is the box's own parent (see richtext.js), reached
     for here only to add the second class that wins. `inherit` rather than a
     fixed disc/decimal so a nested list still gets what its own tag calls
     for. */
  .richtext-editor & li { list-style: inherit; }
  /* A list nested by the indent button, and a paragraph the browser wrapped
     in a blockquote to indent it. */
  & li > ul, & li > ol { margin-bottom: 0; }
  & blockquote {
    margin: 0 0 0.7rem;
    padding-inline-start: 0.8rem;
    border-inline-start: 3px solid var(--line);
  }
}
