/* ===========================================================================
   UTILITIES — THE REPLACEMENT FOR style="".

   An inline style attribute — margin-top one more way, a font-size,
   "display:inline", "white-space:nowrap" — is a small local decision that
   no stylesheet can see, no rule can govern, and no change can ever reach,
   which is how spacing drifts.

   These classes do the same jobs, but every one of them resolves to a token
   in tokens.css. Change --space-4 and every .mt-4 in the system moves
   together. That is the whole difference between a style attribute and a
   utility class, and it is the difference between a system and a pile.

   LOADED LAST so it beats the component layer. A utility is an author saying
   "I know, and I mean it here", and it should win.

   NAMING. The number is the SCALE STEP, not a pixel count: .mt-4 is
   --space-4 is 16px. Learn the six steps once.

   WHEN NOT TO USE THESE. If a page needs the same three utilities in the
   same order more than about four times, that is a component asking to
   exist. Put it in style.css and give it a name.
   =========================================================================== */


/* ---- DISPLAY -------------------------------------------------------------- */
.d-none, .hidden { display: none !important; }
.d-block        { display: block; }
.d-inline       { display: inline; }
.d-inline-block { display: inline-block; }
.d-flex         { display: flex; }
.d-inline-flex  { display: inline-flex; }
.d-grid         { display: grid; }


/* ---- MARGIN ---------------------------------------------------------------
   The all-sides rules come FIRST, so a directional class written after them
   wins on source order — `class="m-0 mb-3"` means what it looks like it
   means. Both are one class deep, so nothing here depends on specificity
   tricks that break the moment somebody adds a parent selector.
   --------------------------------------------------------------------------- */
.m-0 { margin: 0; }
.m-auto { margin-left: auto; margin-right: auto; }

.mt-0 { margin-top: var(--space-0); }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }
.mt-8 { margin-top: var(--space-8); }

.mb-0 { margin-bottom: var(--space-0); }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-7 { margin-bottom: var(--space-7); }
.mb-8 { margin-bottom: var(--space-8); }

.ml-0 { margin-left: var(--space-0); }
.ml-1 { margin-left: var(--space-1); }
.ml-2 { margin-left: var(--space-2); }
.ml-3 { margin-left: var(--space-3); }
.ml-4 { margin-left: var(--space-4); }
.ml-auto { margin-left: auto; }

.mr-0 { margin-right: var(--space-0); }
.mr-1 { margin-right: var(--space-1); }
.mr-2 { margin-right: var(--space-2); }
.mr-3 { margin-right: var(--space-3); }
.mr-4 { margin-right: var(--space-4); }
.mr-auto { margin-right: auto; }


/* ---- PADDING -------------------------------------------------------------- */
/* THE FULL SCALE, WITH NO HOLES. A missing step means a class such as .p-1
   that no stylesheet defines — a class that does nothing, silently, for
   ever. A gap in the middle of a scale is
   worse than no scale at all: the missing step gets replaced by a
   hand-typed pixel value and the drift starts again from there. */
.p-0 { padding: 0; }
.p-1 { padding: var(--space-1); }
.p-2 { padding: var(--space-2); }
.p-3 { padding: var(--space-3); }
.p-4 { padding: var(--space-4); }
.p-5 { padding: var(--space-5); }
.p-6 { padding: var(--space-6); }
.p-7 { padding: var(--space-7); }
.p-8 { padding: var(--space-8); }

.pt-0 { padding-top: var(--space-0); }
.pt-1 { padding-top: var(--space-1); }
.pt-2 { padding-top: var(--space-2); }
.pt-3 { padding-top: var(--space-3); }
.pt-4 { padding-top: var(--space-4); }
.pt-5 { padding-top: var(--space-5); }
.pt-6 { padding-top: var(--space-6); }

.pb-0 { padding-bottom: var(--space-0); }
.pb-1 { padding-bottom: var(--space-1); }
.pb-2 { padding-bottom: var(--space-2); }
.pb-3 { padding-bottom: var(--space-3); }
.pb-4 { padding-bottom: var(--space-4); }
.pb-5 { padding-bottom: var(--space-5); }
.pb-6 { padding-bottom: var(--space-6); }


/* ---- TYPE ----------------------------------------------------------------- */
.text-2xs  { font-size: var(--text-2xs); }
.text-xs   { font-size: var(--text-xs); }
.text-sm   { font-size: var(--text-sm); }
.text-md   { font-size: var(--text-md); }
.text-base { font-size: var(--text-base); }
.text-lg   { font-size: var(--text-lg); }
.text-xl   { font-size: var(--text-xl); }
.text-2xl  { font-size: var(--text-2xl); }

.fw-normal { font-weight: var(--weight-normal); }
.fw-medium { font-weight: var(--weight-medium); }
.fw-bold   { font-weight: var(--weight-bold); }
.fw-heavy  { font-weight: var(--weight-heavy); }

.text-left   { text-align: left; }
.text-center { text-align: center; }
.text-right  { text-align: right; }

.leading-tight { line-height: var(--leading-tight); }
.leading-body  { line-height: var(--leading-body); }

/* PROSE THAT STAYS READABLE. Past about 68 characters the eye loses its
   place coming back to the start of the next line. */
.measure { max-width: var(--measure); }

/* ONE LINE, WITH AN ELLIPSIS. Needs the min-width: 0 that rules.css already
   gives grid and flex children, or it silently does nothing. */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.nowrap { white-space: nowrap; }
.wrap-anywhere { overflow-wrap: anywhere; word-break: break-word; }


/* ---- SIZE ----------------------------------------------------------------- */
.w-full { width: 100%; }
.w-auto { width: auto; }
.max-full { max-width: 100%; }


/* ---- FLEX HELPERS ---------------------------------------------------------
   A row that wraps, with a gap from the scale. This is what most of the
   hand-written `display:flex;gap:10px` inline styles reach for.
   --------------------------------------------------------------------------- */
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-inline);
}
.row-tight { gap: var(--space-1); }
.row-loose { gap: var(--gap-content); }
.row-top   { align-items: flex-start; }
.row-between { justify-content: space-between; }
.row > * { min-width: 0; }

.grow   { flex: 1 1 auto; min-width: 0; }
.noshrink { flex: 0 0 auto; }


/* ---- COLOUR ROLES ---------------------------------------------------------
   Named by meaning, not by colour, so the day the palette moves nothing here
   has to be found and edited.
   --------------------------------------------------------------------------- */
.text-soft   { color: var(--text-soft); }
.text-strong { color: var(--text); }
.text-brand  { color: var(--red-deep); }


/* ---- ACCESSIBILITY --------------------------------------------------------
   Visible to a screen reader, invisible on screen. For the label a sighted
   person infers from an icon and a blind person cannot.
   --------------------------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
