/* Wrench Addict styles.
   Written "mobile first": the basic rules suit a phone, and the @media rule
   near the bottom adjusts things for wider screens. */

/* Colours in one place, so they're easy to change later. */
:root {
  --text: #1f2933;
  --muted: #616e7c;
  --background: #f5f7fa;
  --card: #ffffff;
  --border: #d9e2ec;
  --accent: #1f6feb;
  --accent-dark: #1858c4;  /* a blue button under the mouse */
  --accent-soft: #e8f0fe;  /* an outlined button under the mouse */
  --accent-text: #ffffff;
  --error-bg: #fde8e8;
  --error-text: #9b1c1c;
  --error-dark: #7a1515;   /* the red Confirm button under the mouse */
  --ok-bg: #e3f9e5;
  --ok-text: #1e5e2a;
  --warn-bg: #fff4d6;
  --warn-text: #7a4f01;
  --likely-bg: #ffe4d1;
  --likely-text: #9a3412;
}

* {
  box-sizing: border-box; /* widths include padding and border, which makes layout predictable */
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px; /* 16px or more stops iPhones from zooming in on form fields */
  line-height: 1.5;
  color: var(--text);
  background: var(--background);
}

/* ---------- Header ---------- */

.site-header {
  display: flex;
  flex-wrap: wrap; /* on a narrow phone, the menu moves onto its own line under the name */
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  padding: 0.75rem 1rem;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}

.site-name {
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap; /* never split "Wrench Addict" over two lines */
  display: inline-flex; /* the icon and the name side by side, centred */
  align-items: center;
  gap: 0.4rem;
}

.site-header nav {
  display: flex;
  gap: 1rem;
}

main {
  max-width: 50rem;
  margin: 0 auto;
  padding: 1rem;
}

a {
  color: var(--accent);
}

h1 {
  font-size: 1.5rem;
  margin: 0.5rem 0 1rem;
}

/* Three heading sizes only: the page title (h1), sections (h2), and sub-sections and card
   titles (h3; cards style their title the same whatever its level, see .card below). */
h2 {
  font-size: 1.25rem;
  margin: 1.5rem 0 0.75rem;
}

h3 {
  font-size: 1.1rem;
  margin: 1.25rem 0 0.5rem;
}

.muted {
  color: var(--muted);
}

/* "← Back" link at the top of a page */
.breadcrumb {
  margin: 0;
}

/* Keep the line breaks someone typed into a notes box */
.notes {
  white-space: pre-line;
}

/* ---------- Details list (label: value pairs) ---------- */

.details {
  display: grid;
  grid-template-columns: max-content 1fr; /* labels as narrow as possible, values take the rest */
  gap: 0.25rem 1rem;
  margin: 0 0 1rem;
  padding: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.details dt {
  font-weight: 600;
}

.details dd {
  margin: 0;
}

/* ---------- Messages from flash() ---------- */

.flash {
  padding: 0.75rem 1rem;
  border-radius: 6px;
  background: var(--ok-bg);
  color: var(--ok-text);
}

.flash-error {
  background: var(--error-bg);
  color: var(--error-text);
}

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

button,
.button {
  display: inline-block;
  padding: 0.5rem 1rem;
  font: inherit;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-text);
  text-decoration: none;
  cursor: pointer;
}

button.secondary,
.button.secondary {
  background: var(--card);
  color: var(--accent);
}

/* Under the mouse: a blue button gets darker, an outlined one gets a light blue fill.
   (:not(.link): buttons that look like links keep looking like links.) */
button:not(.link):hover,
.button:hover {
  background: var(--accent-dark);
  border-color: var(--accent-dark);
}

button.secondary:hover,
.button.secondary:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* Moving through the page with the Tab key: a clear ring around the button or link you're on.
   :focus-visible only shows it for the keyboard, not after a tap or click. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* A row of buttons: the same everywhere (page headings, cards, the end of forms). On a narrow
   phone, buttons that don't fit drop onto the next line. Buttons are never squeezed: a button
   only wraps its words if it's wider than the whole row on its own (max-width). */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start; /* buttons keep their own height when a Confirm box opens beside them */
  gap: 0.5rem;
}

.actions > * {
  max-width: 100%;
  overflow-wrap: anywhere; /* a word longer than the row (a very long name) breaks, too */
}

.actions form {
  margin: 0;
}

/* ---------- Confirm buttons (the confirm_button macro in templates/_macros.html) ----------
   The button opens a pop-up (an element with the popover attribute): the browser shows it in the
   middle of the screen, over the page, and closes it with Cancel, Esc or a tap outside it. */

.confirm-popup {
  width: min(26rem, calc(100vw - 2rem)); /* never wider than a phone screen, less 1rem each side */
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

/* The page behind the pop-up is dimmed, so it's clear the pop-up needs an answer. */
.confirm-popup::backdrop {
  background: rgba(0, 0, 0, 0.35);
}

.confirm-question {
  margin: 0 0 0.5rem;
  font-weight: 600;
}

.confirm-popup .actions {
  margin-top: 1rem;
}

.confirm-popup form {
  margin: 0;
}

/* The Confirm button itself: red, so it's clear this is the one that acts. */
button.danger {
  border-color: var(--error-text);
  background: var(--error-text);
  color: #ffffff;
}

button.danger:hover {
  background: var(--error-dark);
  border-color: var(--error-dark);
}

.confirm-note {
  margin: 0;
  color: var(--muted);
}

/* ---------- Vehicle list ---------- */

/* A heading with its buttons beside it (e.g. "Your garage" with Add to garage). On a narrow
   phone, the buttons drop below the heading if they don't fit. The space around the heading
   goes on the whole row (same as a heading on its own), so the buttons line up with the
   heading text and get the same space when they've dropped below it. */
.page-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin: 0.5rem 0 1rem;
}

.page-heading:has(> h2) {
  margin: 1.5rem 0 0.75rem;
}

.page-heading h1,
.page-heading h2 {
  margin: 0;
}

/* The title (and its place line) may shrink to the row's width, so a very long name wraps
   (or is cut short with "…" in the place line) instead of widening the page. */
.page-heading > div:not(.actions),
.page-heading > h1,
.page-heading > h2 {
  min-width: 0;
  max-width: 100%;
}

/* The place line under a page's title: where the thing belongs (Garage › RAV4 › Oil change),
   small and grey so it doesn't compete with the title. The negative top margin pulls it up
   under a plain title (the title's 1rem space below and this -0.75rem leave 0.25rem). */
.place {
  margin: -0.75rem 0 1rem;
  font-size: 0.9rem;
  color: var(--muted);
}

/* Each step stays in one piece ("Service on 18 Mar 2026"); the line wraps between steps.
   A step longer than the whole line (a very long name) is cut short with "…". */
.place a {
  white-space: nowrap;
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}

/* Beside buttons, the title and its place line are in a <div> of their own. */
.page-heading .place {
  margin: 0.15rem 0 0;
}

/* ---------- "Choose how to start" panel (vehicle page, a vehicle with no items yet) ---------- */

/* An archived machine's page: the notice with Restore, above its details. */
.archived-panel {
  margin-bottom: 1rem;
}

.start-panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
}

.start-panel > p {
  margin: 0 0 0.75rem;
}

/* One option per row. On a phone the description goes under its button (one column);
   the wide-screen rule near the bottom puts it beside the button instead. */
.start-options {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 1rem;
}

.start-options li {
  display: grid;
  gap: 0.25rem;
}

.start-options .button {
  text-align: center;
}

.card-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
  margin-bottom: 0.75rem;
}

.card h2,
.card h3,
.card h4 {
  font-size: 1.1rem;
  margin: 0;
}

.card h2 a,
.card h3 a,
.card h4 a {
  color: var(--text);
}

.card p {
  margin: 0.25rem 0 0;
}

.card.archived {
  opacity: 0.7;
}

/* A card's buttons: under its text on a phone (beside it on a wider screen, see the end). */
.card .actions {
  margin-top: 0.75rem;
}

.tag {
  font-size: 0.8rem;
  font-weight: normal;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--border);
  color: var(--muted);
}

/* Due status badges (see due.py): the class is "status status-overdue" etc. */
.status {
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap; /* keep "Due soon" on one line */
  background: var(--border);
  color: var(--muted);
}

.status-overdue {
  background: var(--error-bg);
  color: var(--error-text);
}

/* Likely overdue: orange, between Overdue's red and Due soon's amber. */
.status-likely_overdue {
  background: var(--likely-bg);
  color: var(--likely-text);
}

.status-due_soon {
  background: var(--warn-bg);
  color: var(--warn-text);
}

.status-ok {
  background: var(--ok-bg);
  color: var(--ok-text);
}

/* In storage: on hold, so it keeps the plain grey of .status. */

/* ---------- Item specs (materials, tools, fasteners) ---------- */

.spec-list {
  list-style: none;
  padding: 0;
  margin: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

/* ">" means direct children only, so these rules don't also hit the linked-products list inside. */
.spec-list > li {
  display: flex;
  flex-wrap: wrap; /* lets the linked-products list drop onto its own full-width line */
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.6rem 1rem;
}

.spec-list > li + li {
  border-top: 1px solid var(--border); /* a line between rows, not above the first */
}

/* Catalog products linked to a material, listed under it with a small heading. */
.linked-products {
  flex-basis: 100%; /* take a whole line of its own, under the description and actions */
}

.linked-heading {
  margin: 0;
  font-size: 0.9rem;
  color: var(--muted);
}

/* Rows with an action on the right (linked products and their Unlink): the text on the left,
   the action lined up on the right, like the other actions in a list. On a narrow phone the
   action drops under the text. */
.link-rows {
  list-style: none;
  padding: 0;
  margin: 0.25rem 0 0;
}

.link-rows > li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 0 1rem;
}

.link-rows > li + li {
  margin-top: 0.25rem;
}

.tag.role-preferred {
  background: var(--ok-bg);
  color: var(--ok-text);
}

/* Each detail (spec, quantity) goes on its own line under the description. */
.spec-detail {
  display: block;
  color: var(--muted);
}

/* The torque number is what you look for with a wrench in hand, so make it stand out. */
.spec-detail.torque-value {
  color: var(--text);
  font-weight: 600;
}

.spec-actions {
  display: flex;
  gap: 1rem;
  flex-shrink: 0; /* don't squash the Edit/Delete links on narrow screens */
}

.spec-actions form {
  margin: 0;
}

/* The ▲ ▼ buttons that reorder a list (see the move_buttons macro in items/_specs.html). */
button.link.move {
  text-decoration: none;
  padding: 0 0.15rem;
}

/* Next to full-size buttons (the vehicle list's Edit/Archive), give ▲ ▼ the same height so they
   line up, which also makes them easier to tap on a phone. */
.actions button.link.move {
  padding: 0.5rem 0.25rem;
}

/* The triangle inside a ▲ ▼ button (the arrow macro in _macros.html): the same size everywhere. */
button.link.move .arrow {
  display: block;
  width: 0.8rem;
  height: 0.65rem;
}

/* The first row's ▲ and the last row's ▼ have nowhere to go: grey them out. */
button.link.move:disabled {
  color: var(--border);
  cursor: default;
}

/* A button that looks like a link, for small actions like Delete. */
button.link {
  padding: 0;
  border: none;
  background: none;
  color: var(--accent);
  text-decoration: underline;
}

/* On touch screens, the small actions in list rows (Edit, Delete, Link product, Unlink, Remove,
   ▲ ▼) are at least 44 px tall and wide, the size recommended for a fingertip, so the one next
   to it isn't tapped by mistake. The words stay the same size; only the area you can tap grows.
   "pointer: coarse" means the main pointer is a finger, so a computer with a mouse keeps the
   compact rows. */
@media (pointer: coarse) {
  button.link,
  .spec-actions > a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
    min-width: 2.75rem;
  }

  /* The 44 px boxes already space the links apart; a smaller gap keeps a row on one line, and
     wrapping is the fallback so a long row never scrolls sideways. */
  .spec-actions {
    gap: 0.25rem 0.5rem;
    flex-wrap: wrap;
  }
}

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

/* A garage's invite code on the Settings page: big enough to read out or copy. */
.invite-code code {
  font-size: 1.25rem;
  padding: 0.25rem 0.5rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
  user-select: all; /* one tap or click selects the whole code */
}

/* Log in and Sign up: a few short boxes, so not the full page width on a computer. */
.narrow-form {
  max-width: 24rem;
}

.form label {
  display: block;
  margin-bottom: 1rem;
  font-weight: 600;
}

.form input:not([type="checkbox"]):not([type="radio"]),
.form select,
.form textarea {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.5rem;
  font: inherit;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--card);
}

.form fieldset {
  border: 1px solid var(--border);
  border-radius: 6px;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
}

.form legend {
  font-weight: 600;
  padding: 0 0.25rem;
}

.form label.checkbox {
  font-weight: normal;
  margin-bottom: 0.5rem;
}

/* A radio button with a sentence or two beside it: the text wraps beside the button, not under it. */
.form label.choice {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  font-weight: normal;
  margin-bottom: 0.75rem;
}

/* A small grey note under a box, e.g. "Last: 87,650 km on 23 Oct 2026" under a reading. */
.form .box-note {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.85rem;
  font-weight: normal;
  color: var(--muted);
}

.form .muted {
  margin: 0 0 0.75rem;
  font-size: 0.9rem;
}

/* Two boxes side by side on every screen size, e.g. "Every [12] [months]". */
.form .pair {
  display: flex;
  gap: 1rem;
}

.form .pair label {
  flex: 1;
  margin-bottom: 0.5rem;
}

/* Boxes for numbers, money and dates are short (they hold a few characters); names and notes
   take the full width. On a phone, both are about as wide as the screen anyway. */
.form input[inputmode="numeric"],
.form input[inputmode="decimal"],
.form input[type="date"] {
  max-width: 12rem;
}

.required {
  font-weight: normal;
  color: var(--muted);
}

/* A box with a problem after a form was sent (the problem_mark macro, aria-invalid="true"):
   red border and a light red fill, so it's easy to find. A group of boxes (fieldset) with a
   problem in it gets a red border too, and so does a group flagged as a whole ("Tick at least
   one job"). */
.form [aria-invalid="true"]:is(input, select, textarea) {
  border-color: var(--error-text);
  background: var(--error-bg);
}

.form fieldset:has([aria-invalid="true"]),
.form fieldset[aria-invalid="true"] {
  border-color: var(--error-text);
}

/* ---------- Service log ---------- */

/* The one-off job boxes on the Log service form, stacked with a little space between. */
.form input.one-off {
  margin-bottom: 0.5rem;
}

/* Hide an empty one-off box when the box just before it is also empty, so only one blank
   box shows at a time (same idea as the extra rows on the job details form). */
.form input.one-off:placeholder-shown + input.one-off:placeholder-shown {
  display: none;
}

/* The "Add a job" box under a visit's jobs. */
.add-job {
  margin-top: 1rem;
  padding: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.add-job h3 {
  margin: 0 0 0.75rem;
}

/* ---------- Job details form (templates/jobs/details.html) ----------
   These rules use :has(), which lets CSS react to what's inside an element
   (e.g. "a row whose tick box is unticked"). That's how the form shows and hides
   boxes as you fill it in, without any JavaScript. */

.step {
  margin: 0.5rem 0 0;
}

.form .used-row,
.form .extra-row {
  background: var(--card);
  margin-bottom: 0.75rem;
}

.form .used-row > label.checkbox {
  margin-bottom: 0;
}

.used-fields {
  margin-top: 0.75rem;
}

/* A spec material that wasn't used: hide its product/quantity/cost boxes. */
.used-row:has(> label input[type="checkbox"]:not(:checked)) .used-fields {
  display: none;
}

/* Brand and part number are only needed when "Other" is chosen as the product.
   (A material with no linked products has no dropdown, so they always show.) */
.used-row:has(select option[value="other"]:not(:checked)) .other-fields {
  display: none;
}

/* Extras: hide an empty row if the row before it is also empty, so only one blank
   row shows at a time. ":placeholder-shown" means "the box is empty, showing its hint". */
.extra-row:has(.extra-description:placeholder-shown) + .extra-row:has(.extra-description:placeholder-shown) {
  display: none;
}

/* Three boxes side by side on every screen size: Quantity, Unit, Cost. */
.form .trio {
  display: flex;
  gap: 0.75rem;
}

.form .trio label,
.form .used-fields .pair label,
.form .extra-row .pair label {
  flex: 1;
  min-width: 0; /* let the boxes shrink to fit a narrow phone screen */
  margin-bottom: 0.5rem;
}

/* The item's specs on a job page, in a box that can be folded away. */
.specs-box {
  margin-top: 1.5rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
}

.specs-box summary {
  font-weight: 600;
  cursor: pointer;
}

/* ---------- Vehicle form ---------- */

/* Usage warnings only matter for km/hours: hide the box when neither meter is ticked,
   and each estimate box when its own meter isn't ticked. */
.form:has(input[name="tracks_km"]:not(:checked)):has(input[name="tracks_hours"]:not(:checked)) .usage-fields,
.form:has(input[name="tracks_km"]:not(:checked)) .est-km,
.form:has(input[name="tracks_hours"]:not(:checked)) .est-hours {
  display: none;
}

/* ---------- Spending on the dashboard (templates/dashboard.html) ---------- */

/* The four money figures: wider tiles than the status ones, so 4 in a row on a computer and
   2 x 2 on a phone. ".tiles.money-tiles" (both classes) so this wins over the .tiles rule
   further down, which would otherwise set 3 columns on a phone. */
.tiles.money-tiles {
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
}

.money-tiles .tile {
  font-weight: normal;
  color: var(--muted);
}

.money-tiles .tile-count {
  color: var(--text);
  font-weight: 600;
}

/* ---------- Add vehicle, step 1: pick a type (templates/vehicles/pick_type.html) ---------- */

/* A grid of buttons: as many columns as fit (each at least 11rem wide), so one column
   on a phone and three or four on a computer. */
.type-picker {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.5rem;
}

.type-picker .button {
  display: block;
  height: 100%; /* buttons in the same row line up even when a label wraps */
  text-align: left;
}

/* ---------- Add common items (templates/items/suggested.html) ---------- */

.form .suggestion-name {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin: 0;
  font-weight: 600;
  cursor: pointer;
}

.suggestion-name input {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
}

/* The interval boxes side by side: as many as fit, each at least 6.5rem wide. */
.suggestion-intervals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.form .suggestion-intervals label {
  margin: 0;
  font-weight: normal;
  font-size: 0.9rem;
}

/* Fade a suggestion while it's unticked, so the ticked ones stand out. */
.suggestion:has(.suggestion-name input:not(:checked)) .suggestion-intervals,
.suggestion:has(.suggestion-name input:not(:checked)) .muted {
  opacity: 0.5;
}

/* ---------- Get ready checklist (templates/items/get_ready.html) ---------- */

.checklist {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.checklist li + li {
  border-top: 1px solid var(--border);
}

/* The whole line is the tick box's label, so tapping anywhere on it ticks the box. */
.check-row {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.6rem 1rem;
  cursor: pointer;
}

.check-row input {
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.15rem;
  flex-shrink: 0;
}

/* Ticked: cross the line out and fade it. */
.check-row:has(input:checked) > span {
  text-decoration: line-through;
  color: var(--muted);
}

/* Parts of a page meant only for paper (e.g. the write-in lines on Get ready). */
.print-only {
  display: none;
}

/* ---------- Printing (any page; tuned for the Get ready checklist) ----------
   These rules only apply when a page is printed or saved as a PDF. */
@media print {
  @page {
    margin: 15mm;
  }

  /* Leave out the menu, buttons and messages; show the paper-only parts. */
  .site-header,
  .no-print,
  .flash {
    display: none;
  }

  .print-only {
    display: block;
  }

  /* Plain black on white, with no screen colours, card backgrounds or rounded boxes. */
  body {
    background: #fff;
    color: #000;
    font-size: 10.5pt;
  }

  main {
    max-width: none;
    padding: 0;
  }

  a {
    color: #000;
    text-decoration: none;
  }

  .muted,
  .spec-detail,
  .tag {
    color: #333;
  }

  .tag {
    background: none;
    padding: 0;
  }

  .details,
  .checklist {
    background: none;
    border: 1px solid #999;
    border-radius: 0;
  }

  .checklist li + li {
    border-top-color: #999;
  }

  /* Tighter spacing than on screen, so a typical job fits on one sheet. */
  h1 {
    margin: 0 0 0.5rem;
  }

  h2 {
    margin: 0.9rem 0 0.4rem;
  }

  .details {
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.5rem;
  }

  .check-row {
    padding: 0.3rem 0.75rem;
  }

  /* Empty boxes to tick with a pen. appearance: none replaces the browser's own tick box
     with a plain square, so it prints clearly and never prints as ticked. */
  .check-row input {
    appearance: none;
    border: 1.5px solid #000;
    border-radius: 2px;
    background: #fff;
  }

  /* Don't print screen ticks as crossed-out lines: the sheet starts clean. */
  .check-row:has(input:checked) > span {
    text-decoration: none;
    color: inherit;
  }

  .spec-detail.torque-value {
    color: #000;
    font-weight: 700;
  }

  /* Keep a heading with its list, and each checklist line in one piece, across pages. */
  h2 {
    break-after: avoid;
  }

  .checklist li,
  .write-in {
    break-inside: avoid;
  }

  /* "Date: ______  Cost: ______": lines to write on, sharing the rest of the row. */
  .write-in p {
    display: flex;
    gap: 0.5rem;
    margin: 0 0 0.7rem;
  }

  .write-line {
    flex: 1;
    border-bottom: 1px solid #000;
  }
}

/* ---------- Dashboard ---------- */

/* 1. Status tiles: as many columns as fit (each at least 6.25rem), so 3 on a phone. */
.tiles {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.25rem, 1fr));
  gap: 0.5rem;
}

.tile {
  display: block;
  height: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
}

.tile-count {
  display: block;
  font-size: 1.5rem;
  line-height: 1.1;
}

/* The tiles use the same colours as the status badges. */
.tile-overdue { background: var(--error-bg); color: var(--error-text); border-color: transparent; }
.tile-likely_overdue { background: var(--likely-bg); color: var(--likely-text); border-color: transparent; }
.tile-due_soon { background: var(--warn-bg); color: var(--warn-text); border-color: transparent; }
.tile-ok { background: var(--ok-bg); color: var(--ok-text); border-color: transparent; }

/* A tile with nothing in it: greyed out, and not a link. */
.tile-empty {
  color: var(--muted);
  opacity: 0.6;
}

/* 2. Progress bars: a grey track with a coloured part whose width is the percentage. */
.progress-list {
  display: grid;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.progress-text {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 1rem;
  margin: 0 0 0.25rem;
}

.progress-bar {
  height: 0.6rem;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden; /* keeps the coloured part inside the rounded ends */
}

.progress-bar > span {
  display: block;
  height: 100%;
}

.progress-ok {
  background: var(--ok-text);
}

.progress-setup {
  background: var(--muted);
}

.progress-hint {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
}

/* 3. One line per vehicle: its name, then its counts (which wrap under it on a phone). */
.vehicle-summary {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.vehicle-summary li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.75rem;
  padding: 0.4rem 1rem;
}

.vehicle-summary li + li {
  border-top: 1px solid var(--border);
}

.vehicle-summary a {
  font-weight: 600;
}

.vehicle-counts {
  color: var(--muted);
  font-size: 0.95rem;
}

/* Coming up (dashboard): the job and its machine on the left, when it's due on the right. */
.coming-up li {
  justify-content: space-between;
}

.vehicle-summary .machine {
  font-weight: normal;
}

/* Counts that need attention, in their status colours. */
.count-overdue { color: var(--error-text); font-weight: 600; }
.count-likely_overdue { color: var(--likely-text); font-weight: 600; }
.count-due_soon { color: var(--warn-text); font-weight: 600; }

/* 4. Each status group is a <details> box: click its heading to fold it away or open it. */
.dashboard-group {
  margin-bottom: 0.5rem;
}

.dashboard-group > summary {
  cursor: pointer;
}

/* Keep the group heading on the same line as the fold arrow. */
.dashboard-group > summary h3 {
  display: inline;
}

.dashboard-group .card-list {
  margin-top: 0.75rem;
}

/* ---------- Wider screens (tablets and computers) ---------- */

@media (min-width: 40rem) {
  /* Put Year / Make / Model side by side instead of stacked. */
  .form .row {
    display: flex;
    gap: 1rem;
  }

  .form .row label {
    flex: 1;
  }

  /* Put the Edit/Archive buttons to the right of the vehicle details. */
  .card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
  }

  /* The buttons keep their full size; the text beside them wraps instead (so a long
     description never squeezes "Log service" onto two lines). */
  .card .actions {
    margin-top: 0;
    flex-shrink: 0;
  }

  /* "Choose how to start": every button in a 16rem column, its description beside it. */
  .start-options li {
    grid-template-columns: 16rem 1fr;
    align-items: center;
    gap: 1rem;
  }
}

/* Add common jobs: the jobs already on this machine, folded into one line under the choices. */
.already-added {
  margin-top: 1.5rem;
  color: var(--muted);
}

.already-added summary {
  cursor: pointer;
}

.already-added ul {
  margin: 0.5rem 0 0;
  padding-left: 1.25rem;
}

/* A very long word (e.g. a pasted 200-character name with no spaces) breaks onto the next line
   instead of making the page scroll sideways. Ordinary words still wrap between words. */
h1, h2, h3, h4, p, dd, li, label, legend, summary, .card-main {
  overflow-wrap: anywhere;
}
