/* Nunito Sans served from here, not from Google Fonts: the variable font of
   @fontsource-variable/nunito-sans 5.3.0 (SIL OFL 1.1, licence beside the
   files), one file per script covering every weight in use (400-700).
   docs/ui/implementation.md, "Changes outside `dashboard/`". */
@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url("vendor/nunito-sans-5.3.0/nunito-sans-latin-ext-wght-normal.9359f35055cf.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url("vendor/nunito-sans-5.3.0/nunito-sans-latin-wght-normal.e010923d59d4.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* The scrollbar's room is kept on every page, so a long page and a short
   one centre the content at the same place: switching the profile's tabs
   does not shift it sideways where scrollbars take up width (Windows). */
html {
  scrollbar-gutter: stable;
}

/* The hidden attribute always hides: the scripts hide rows that carry a
   display class of their own (flex, grid), which would otherwise win. */
[hidden] {
  display: none !important;
}

/* 14px everywhere but the page title: every text of the Figma frames is
   Montserrat 14, the title 24 Medium. */
/* Typography (decision of 2026-09-21, docs/ui/elements.md, "Design system" and "Typography"): Nunito Sans
   at the 14px base of the model, and a secondary tier at 12px - email under
   the name, section labels, badges, form help (daisyUI's own 12px for
   fieldset labels). Chosen over the theme's Montserrat after a check
   against the SPP portal: same base size, closer letterforms. The Figma
   file carries the same values: the font variable main/fontFamily/primary
   (mode design4pv), the secondary text of Table / Cell bound to
   fields/fontSize/sm (12, line 150% = 18px), the menu titles and the
   status badges on the Project page bound to the sm sizes as well. */
body {
  font-family: "Nunito Sans", ui-sans-serif, system-ui, sans-serif;
  font-size: 0.875rem;
  line-height: 1.5;
}
.fieldset {
  font-size: 0.875rem;
}

/* The bar of bulk actions appears once a row is ticked - no script needed. */
.bulk-bar {
  display: none;
}
form:has(tbody input[type="checkbox"]:checked) .bulk-bar {
  display: flex;
}

/* Focus on fields as in the SPP portal (measured there): no outline, the
   border in the accent colour at 30% and a soft 2px ring at 18%. daisyUI's
   own 2px solid outline reads as a heavy double ring. */
.input:focus,
.input:focus-within,
.select:focus,
.select:focus-within,
.select:open,
.textarea:focus,
.textarea:focus-within,
.file-input:focus,
.file-input:focus-within {
  outline: none;
  border-color: color-mix(in oklab, var(--color-accent) 30%, transparent);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--color-accent) 18%, transparent);
}

/* The browser's own x of a search field empties the field but leaves the
   list filtered; the search box has a reset link of its own instead. */
input[type="search"]::-webkit-search-cancel-button {
  appearance: none;
}

/* Checkboxes as the file's Checkbox (xs): unchecked it is the default
   variant - white fill, border base-content at 20%; checked it is the
   accent variant - accent fill, white mark. checkbox-accent alone would
   colour the unchecked border too, which the file does not. daisyUI's
   rules sit in a cascade layer, so these win and name the checked fill
   themselves. */
.checkbox {
  background-color: var(--color-base-100);
}
.checkbox:checked,
.checkbox:indeterminate {
  --input-color: var(--color-accent);
  background-color: var(--color-accent);
  color: var(--color-accent-content);
}

/* The calendar of a date range field (dashboard/date_range.html) at the
   file's Calendar size: 32px days, so a month is 224 wide and, with
   daisyUI's 16px padding, the calendar is as wide as a filter field (256).
   Cally draws its days at 36px and daisyUI's cally class has no size
   modifier. Its day buttons sit in a shadow root, where a button takes the
   browser's font, not the page's. */
.cally ::part(day) {
  inline-size: 2rem;
  block-size: 2rem;
  font-family: inherit;
}
/* The year above the month at 14 Regular and the weekday letters at 12, as
   in the file's Calendar. Cally draws the year bold and sized from the text
   around it; the weekday cells carry the day part too, so daisyUI's 0.7rem
   for days reaches them and the text-xs on the calendar does not. */
.cally::part(heading) {
  font-size: 0.875rem;
  font-weight: 400;
}
.cally ::part(th) {
  font-size: 0.75rem;
}
/* Chosen dates in accent, as a ticked checkbox and a highlighted menu item;
   daisyUI's cally class paints them base-content and has no colour
   modifier. Cally declares a --color-accent of its own (black) on the
   calendar, which hides the theme's, so the theme colour is taken on the
   field around it under another name. */
[data-date-range] {
  --date-range-accent: var(--color-accent);
  --date-range-accent-content: var(--color-accent-content);
}
.cally ::part(selected),
.cally ::part(selected):hover {
  background: var(--date-range-accent);
  color: var(--date-range-accent-content);
}

/* While live search waits for the server the list fades a little, so a
   keystroke visibly did something; htmx sets the class on <main>. */
main table {
  transition: opacity 150ms;
}
main.htmx-request table {
  opacity: 0.5;
}

/* One focus ring for what daisyUI gives none of its own - a Home tile, a
   catalog card, a link in a table, an "i", the avatar - instead of the
   browser's, which takes the system's accent colour: the ring of daisyUI's
   buttons (Kostiantyn, 2026-10-25). In the base layer, so every daisyUI
   component keeps its own: a menu item's highlight, a field's border. */
@layer base {
  :focus-visible {
    outline: 2px solid var(--color-base-content);
    outline-offset: 2px;
  }
}

/* A menu's current item - the sidebar's section, a picker's choice - is
   already marked, and daisyUI shows no focus on it at all: it gets the
   ring, as a picker opened by a key puts the focus there. */
.menu .menu-active:focus-visible {
  outline: 2px solid var(--color-base-content);
  outline-offset: 2px;
}

/* Below lg the menu button is a label of the sidebar's checkbox, and the
   checkbox, invisible, takes the focus (base.html): the button shows the
   ring the other buttons get, as if it had the focus itself. */
.drawer-toggle:focus-visible ~ .drawer-content [data-menu-button] {
  outline: 2px solid var(--color-base-content);
  outline-offset: 2px;
}

/* Menus open on Enter, Space or a click, not when the focus comes to them
   (docs/ui-standards.md, rule 35): dashboard.js marks the page with
   data-menus and sets dropdown-open on the menu it opens. Until then a
   dropdown stays closed while it has the focus - daisyUI opens one for as
   long as the focus is inside it. Without the script daisyUI's way stays.
   Filters (a details element) and the searchable picker, which opens as
   one types, are not menus of this kind. daisyUI also lets a click through
   the button of an open dropdown, so that a click outside closes it; here
   the button takes the click, which closes the menu. */
:root[data-menus] .dropdown:not(details, [data-picker-search], .dropdown-open) .dropdown-content {
  display: none;
}
:root[data-menus] .dropdown > [role="button"] {
  pointer-events: auto;
}
