/* ==========================================================================
   Utility classes.
   Loaded last in cascade so utilities win on tie against component rules.

   Spacing scale (used by gap-*, m*-*, p-*):
     q = 0.25rem   1 = 0.5rem   2 = 1rem   3 = 1.5rem   4 = 2rem   6 = 3rem
   Naming: {prop}{axis?}-{step}
     prop  = m | p | gap
     axis  = t/b/l/r (single side) | x/y (axis pair) | omitted = all sides
     step  = scale token (above)
   Reintroduce dropped values (mt-3, p-3, gap-3, etc.) only when a view needs
   them; don't pre-emptively fill the grid.
   ========================================================================== */

/* Layout containers */
.page         { max-width: 800px; margin: 0 auto; }

/* Screen-reader-only content (visually hidden, still announced). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Flex primitives */
.flex         { display: flex; }
.flex-1       { flex: 1; }
.flex-wrap    { flex-wrap: wrap; }
.flex-nowrap  { flex-wrap: nowrap; }
.shrink-0     { flex-shrink: 0; }

/* Compound semantic flex helpers */
.stack        { display: flex; flex-direction: column; gap: 0.5rem; }
.cluster      { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.row          { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; }

/* Align / justify */
.items-center { align-items: center; }
.items-start  { align-items: flex-start; }
.justify-between { justify-content: space-between; }
.justify-end  { justify-content: flex-end; }

/* Gap scale */
.gap-q        { gap: 0.25rem; }
.gap-1        { gap: 0.5rem; }
.gap-2        { gap: 1rem; }
.gap-4        { gap: 2rem; }

/* Margin scale */
.m-0          { margin: 0; }
.mt-0         { margin-top: 0; }
.mt-1         { margin-top: 0.5rem; }
.mt-2         { margin-top: 1rem; }
.mt-4         { margin-top: 2rem; }
.mb-0         { margin-bottom: 0; }
.mb-q         { margin-bottom: 0.25rem; }
.mb-1         { margin-bottom: 0.5rem; }
.mb-2         { margin-bottom: 1rem; }
.mb-3         { margin-bottom: 1.5rem; }
.mb-4         { margin-bottom: 2rem; }
.mr-q         { margin-right: 0.25rem; }
.mr-1         { margin-right: 0.5rem; }
.mr-2         { margin-right: 1rem; }
.ml-1         { margin-left: 0.5rem; }
.my-1         { margin-top: 0.5rem; margin-bottom: 0.5rem; }

/* Padding scale */
.p-2          { padding: 1rem; }
.p-4          { padding: 2rem; }
.p-6          { padding: 3rem; }
.pl-2         { padding-left: 1rem; }

/* Reset top spacing on headings that hug a parent edge */
.flush-top    { margin-top: 0; padding-top: 0; }

/* Sizing */
.basis-full   { flex-basis: 100%; }
.min-h-200    { min-height: 200px; }
.max-h-150-y  { max-height: 150px; overflow-y: auto; }
.max-h-200-y  { max-height: 200px; overflow-y: auto; }
.max-h-250-y  { max-height: 250px; overflow-y: auto; }
.block        { display: block; }

/* Text */
.text-sm      { font-size: 0.9rem; }
.text-xs      { font-size: 0.8rem; }
.text-xxs     { font-size: 0.6rem; }
.text-em-sm   { font-size: 0.9em; }
.text-em-xs   { font-size: 0.8em; }
.text-center  { text-align: center; }
.text-right   { text-align: right; }
.font-bold    { font-weight: bold; }
.nowrap       { white-space: nowrap; }

/* Colours (text) */
.text-muted   { color: var(--medium-grey); }
.text-accent  { color: var(--primary-colour); }
.text-warning { color: var(--secondary-colour); }

/* Misc */
.cursor-pointer { cursor: pointer; }
.opacity-60   { opacity: 0.6; }
.hidden       { display: none !important; }

/* The `hidden` attribute (toggled by Stimulus, e.g. filter-search) hides via
   the UA `[hidden] { display: none }` rule, which any author `display` rule
   (.block, .filter-check-label, etc.) overrides. Force it so hidden always wins. */
[hidden]      { display: none !important; }
.wrap-anywhere { overflow-wrap: anywhere; word-wrap: break-word; white-space: normal; }
