/* Reset, typography, form controls and buttons. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.5;
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 600;
  line-height: 1.2;
  /* Plex Sans is a typeface drawn for engineering documentation, and it
     tightens well. Pulling the tracking in at display sizes is what separates
     a heading from body text set larger, which is all these were: one weight
     and one size apart, on a page where everything else is also 600. */
  letter-spacing: -0.011em;
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-xl);
  font-weight: 650;
  letter-spacing: -0.021em;
}
h2 { font-size: var(--fs-md); }

/* Section labels: small, quiet, uppercase, they should not compete with data */
.section-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 600;
}

p { margin: 0 0 var(--s-3); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

code, .mono {
  font-family: var(--mono);
  font-size: 0.9em;
}

hr {
  border: none;
  border-top: 1px solid var(--rule);
  margin: var(--s-4) 0;
}

/* Focus: always visible, never removed. Keyboard users are first-class. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- Forms --------------------------------------------------------------- */

label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: var(--s-1);
}

/* One control, one look. The list is deliberately not an allowlist of the
   types in use today: a `tel` or a `time` field added later would otherwise
   render unstyled next to its neighbours and nobody would notice until it
   shipped. */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="submit"]):not([type="hidden"]),
select,
textarea {
  width: 100%;
  min-height: var(--control-h);
  padding: 0.4rem 0.55rem;
  font: inherit;
  color: var(--ink);
  background-color: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  /* A field is a slot, so it is recessed: a hairline of shadow along the top
     inner edge, as if the surface had been cut into. It is the counterpart of
     the raised edge on a button, and between them they say which things you
     press and which you type into without a word of explanation. */
  box-shadow: var(--inset);
  transition: border-color var(--speed), box-shadow var(--speed);
}

/* A native select is drawn by the operating system: a different height from
   the input beside it, a different corner radius, and on macOS a blue
   double-chevron in its own well. Two controls in one row looked like two
   different products. So the chrome comes off and the caret is drawn here,
   from two gradients in `currentColor`, which needs no image, no data URI and
   no colour of its own, and so follows the text into dark mode. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 1.9rem;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.05rem center, right 0.75rem center;
  background-size: 0.3rem 0.3rem;
  background-repeat: no-repeat;
}

select:disabled { color: var(--muted); background-color: var(--sunken); }

input:focus,
select:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: var(--inset), var(--focus);
  outline: none;
}

input::placeholder, textarea::placeholder { color: var(--muted); }

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--accent);
  width: 1rem;
  height: 1rem;
}

textarea { min-height: 5rem; resize: vertical; }

/* A multi-select is a list, not a dropdown, so it keeps neither the caret nor
   the single-line height. */
select[multiple] {
  min-height: 9rem;
  padding: 0;
  background-image: none;
}
select[multiple] option { padding: 0.25rem 0.5rem; }

fieldset { border: none; margin: 0; padding: 0; }

.field { margin-bottom: var(--s-4); }

/* Two fields that belong together, side by side, a start and an end date,
   an amount and its status. Collapses to one column on a narrow screen,
   where side-by-side is worse than stacked. `min-width: 0` because a grid
   item defaults to `auto` and a long <select> would push the row wider than
   the form. */
.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0 var(--s-4);
}
.field-row > .field { min-width: 0; }

/* A job number is read aloud and typed into other systems, so it wants to be
   unmistakable and to line up down a column. It used to be set in Plex Mono,
   whose zero carries a slash: at table size the slashes in 10005 line up with
   each other and the number reads as struck through, which on a job book
   means cancelled. Sans with tabular figures keeps the alignment and loses
   the slash. `.mono` stays for machine strings, where telling O from 0 is
   exactly the point: canonical asset names, PO numbers, quote and invoice
   references. */
.jobno {
  font-family: var(--font);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* A list of things to tick, where each row is a sentence rather than a word.
   Django renders a checkbox list as a bare <ul>, which for a line reading
   "CU01003 · 10004 Football Manager 27 · GBP 935.00" is unreadable. */
.check-list {
  display: grid;
  gap: var(--s-2);
  max-height: 24rem;
  overflow-y: auto;
}
.check-list .check-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.check-list .check-row:hover { background: var(--hover); }
.check-list .check-row input { margin-top: 0.15rem; }
.field .help {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: var(--s-1);
}
.field .errors {
  list-style: none;
  margin: var(--s-1) 0 0;
  padding: 0;
  color: var(--danger);
  font-size: var(--fs-sm);
}

.check-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.check-row label { margin: 0; font-weight: 400; }

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  /* Same height as an input, so a button standing in a filter bar next to one
     sits on the same two lines rather than floating between them. */
  min-height: var(--control-h);
  padding: 0.4rem 0.85rem;
  font: inherit;
  font-weight: 500;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  /* Raised, as the counterpart of the recessed field beside it. */
  box-shadow: var(--shadow-sm), var(--edge);
  transition: background var(--speed), border-color var(--speed),
              box-shadow var(--speed), transform var(--speed);
}

.btn:hover { background: var(--hover); text-decoration: none; }

/* Pressed, and it travels. One pixel is enough to feel; more is a toy. */
.btn:active { transform: translateY(1px); box-shadow: none; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent-ink);
  color: #fff;
  font-weight: 600;
  /* Its own lit edge rather than the shared one, which is tuned for a pale
     surface and disappears against a saturated fill. */
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgb(255 255 255 / 18%);
}
.btn-primary:hover { background: var(--accent-ink); border-color: var(--accent-ink); }

.btn-danger { color: var(--danger); border-color: var(--rule-strong); }
.btn-danger:hover { background: var(--danger-soft); border-color: var(--danger); }

.btn-sm { min-height: 1.6rem; padding: 0.2rem 0.5rem; font-size: var(--fs-sm); }
/* A link wearing a button's shape is still a link: no lift, no edge. */
.btn-link {
  box-shadow: none;
}
.btn-link {
  border: none;
  background: none;
  color: var(--accent);
  padding: 0;
}
.btn-link:hover { background: none; text-decoration: underline; }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-row {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  align-items: center;
}
