/* Base stylesheet: the colours, type and layout every page on the site shares.
   Loaded first, on every page, before anything more specific.

   The colour values here are not chosen by eye. Each one is checked by
   scripts/check-contrast.mjs against the background it sits on, so text
   clears the 4.5 to 1 ratio WCAG asks for and the edge of every control
   clears 3 to 1. If you change a colour, change it there too and run
   "npm run check:contrast", or the site quietly stops being readable for
   people who need the contrast. */

/* ---------------------------------------------------------------- *
 * Colour, in two themes
 *
 * The site follows whatever the visitor's device is set to. There is no
 * theme switch, because a switch needs somewhere to remember the choice
 * and this site deliberately stores nothing it does not have to.
 * ---------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Surfaces, lightest first */
  --page: #ffffff;
  --panel: #f4f5f7;
  --raised: #ffffff;

  /* Text */
  --ink: #1b1f24;
  --muted: #565f6b;
  --link: #0b5cab;

  /* The brand amber, carried over from the phone app so the website and
     the app on the worker's phone read as one product. */
  --amber: #f5a300;
  --amber-ink: #241a00;

  /* Meaning. Used for inspection results and for form feedback. */
  --ok: #0f6b3a;
  --ok-bg: #e3f3ea;
  --warn: #6b4c00;
  --warn-bg: #fbf0d6;
  --bad: #b3261e;
  --bad-bg: #fbe9e7;

  /* Lines. Two of them, and the difference matters.
     "hair" is decoration: the rule between two sections. Nothing is lost
     if you cannot see it. "edge" is the outline of something you click or
     type into, which has to be visible to everyone. */
  --hair: #e2e5ea;
  --edge: #767e8a;
  --focus: #0b5cab;

  --shadow: 0 1px 2px rgba(20, 24, 30, .06), 0 6px 20px rgba(20, 24, 30, .05);
  --radius: 12px;
  --measure: 68ch;      /* comfortable reading width for long text */
  --wide: 1080px;       /* page width for everything else */
}

@media (prefers-color-scheme: dark) {
  :root {
    --page: #14181d;
    --panel: #1c2128;
    --raised: #1c2128;
    --ink: #e8ebef;
    --muted: #a3adba;
    --link: #7cb8f7;
    --ok: #4ecb84;
    --ok-bg: #102b1c;
    --warn: #e5b13d;
    --warn-bg: #2c2410;
    --bad: #ff8a80;
    --bad-bg: #331716;
    --hair: #2b323b;
    --edge: #767e8a;
    --focus: #f5a300;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .28);
  }
}

/* ---------------------------------------------------------------- *
 * Reset, kept to the few rules that actually earn their place
 * ---------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  /* System fonts only. A web font would mean a third-party request, which
     would mean loosening the content security policy and having something
     to declare in the privacy policy. Not worth it for a typeface. */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  /* Long words and URLs must not push the page sideways on a phone. */
  overflow-wrap: break-word;
}

img, svg, video { max-width: 100%; height: auto; }

[hidden] { display: none !important; }

/* ---------------------------------------------------------------- *
 * Focus
 *
 * Every interactive thing gets a visible ring when reached by keyboard.
 * :focus-visible rather than :focus so a mouse click does not leave a ring
 * behind, but tabbing always shows one.
 * ---------------------------------------------------------------- */

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Anything that hides the ring is a bug. This makes it loud rather than
   silent, so it gets noticed in review instead of in an audit. */
:focus:not(:focus-visible) { outline: none; }

/* The first thing in the tab order on every page: a link that jumps past
   the navigation, for someone using a keyboard or a screen reader who does
   not want to tab through the menu on every page. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--amber);
  color: var(--amber-ink);
  padding: 12px 18px;
  font-weight: 700;
  z-index: 100;
  text-decoration: none;
}
.skip:focus { left: 0; }

/* ---------------------------------------------------------------- *
 * Type
 * ---------------------------------------------------------------- */

h1, h2, h3, h4 {
  line-height: 1.25;
  margin: 0 0 .5em;
  font-weight: 700;
  letter-spacing: -.01em;
}
h1 { font-size: clamp(1.9rem, 1.4rem + 2.2vw, 2.9rem); }
h2 { font-size: clamp(1.35rem, 1.15rem + 1vw, 1.75rem); margin-top: 2em; }
h3 { font-size: 1.1rem; margin-top: 1.8em; }
h1 + p, h2 + p, h3 + p { margin-top: 0; }

p, ul, ol, dl, table { margin: 0 0 1.1em; }
ul, ol { padding-left: 1.4em; }
li { margin-bottom: .4em; }

a { color: var(--link); text-underline-offset: .18em; }
a:hover { text-decoration-thickness: 2px; }

strong, b { font-weight: 700; }

small, .fine { font-size: .85rem; color: var(--muted); }

code, kbd, samp {
  font-family: ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace;
  font-size: .9em;
  background: var(--panel);
  padding: .12em .38em;
  border-radius: 4px;
}

hr { border: 0; border-top: 1px solid var(--hair); margin: 2.5em 0; }

/* Only ever used for text that must reach a screen reader but not the
   screen: the label on an icon-only button, a heading that structures a
   region visually shown another way. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- *
 * Layout
 * ---------------------------------------------------------------- */

.wrap { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 20px; }

/* A page whose content sits straight inside <main> needs air above the
   heading. Pages built from .section blocks manage their own spacing, so
   this only applies to the long text pages such as the privacy policy. */
main > .wrap { padding-top: 44px; padding-bottom: 24px; }
.prose { max-width: var(--measure); }
.prose h2 { margin-top: 2.2em; }

main { display: block; }
section { margin: 0; }

.section { padding: 56px 0; }
.section--tint { background: var(--panel); border-block: 1px solid var(--hair); }

.grid { display: grid; gap: 20px; }
@media (min-width: 620px) { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 860px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--raised);
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: var(--shadow);
}
.card h3 { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- *
 * Header and footer
 * ---------------------------------------------------------------- */

.siteHeader {
  border-bottom: 1px solid var(--hair);
  background: var(--page);
  position: sticky;
  top: 0;
  z-index: 40;
}

/* On a phone the navigation wraps onto a second line, which makes a sticky
   header about 110px tall and permanently costs an eighth of the screen. The
   pages here are read, not navigated constantly, so the header scrolls away
   and gives the content the whole viewport back. A hamburger menu would keep
   it short but needs JavaScript to open, on pages that otherwise ship none. */
@media (max-width: 600px) {
  .siteHeader { position: static; }
}
.siteHeader .wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 62px;
  flex-wrap: wrap;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  padding: 6px 2px;
  /* It is a link to the home page and it is on every screen, so it gets the
     same 44px target as everything else rather than the 39px the text and
     icon happened to add up to. */
  min-height: 44px;
}
.brand svg { width: 26px; height: 26px; flex: 0 0 auto; }

.nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.nav a {
  color: var(--ink);
  text-decoration: none;
  font-size: .93rem;
  font-weight: 600;
  padding: 9px 11px;
  border-radius: 8px;
}
.nav a:hover { background: var(--panel); text-decoration: underline; }
/* aria-current="page" is what tells a screen reader which page you are on.
   Styling the same attribute means the visual state can never drift from
   the announced one. */
.nav a[aria-current="page"] { background: var(--panel); text-decoration: underline; }

.siteFooter {
  border-top: 1px solid var(--hair);
  background: var(--panel);
  padding: 40px 0 48px;
  margin-top: 60px;
  font-size: .92rem;
}
.siteFooter h2 { font-size: .78rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); margin: 0 0 .7em; }
.siteFooter ul { list-style: none; padding: 0; margin: 0; }
.siteFooter li { margin-bottom: .45em; }
.siteFooter a { color: var(--ink); }
.footCols { display: grid; gap: 28px; grid-template-columns: 1fr; }
@media (min-width: 700px) { .footCols { grid-template-columns: 2fr 1fr 1fr 1fr; } }
.footBase {
  margin-top: 34px; padding-top: 22px;
  border-top: 1px solid var(--hair);
  color: var(--muted); font-size: .85rem;
}
.footBase p { margin: 0 0 .4em; }

/* ---------------------------------------------------------------- *
 * Buttons and links that look like buttons
 * ---------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font: inherit;
  font-weight: 700;
  text-decoration: none;
  padding: 12px 20px;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: pointer;
  /* 44px is the touch target size a thumb in a glove can actually hit. */
  min-height: 44px;
}
.btn--primary { background: var(--amber); color: var(--amber-ink); border-color: var(--amber); }
.btn--primary:hover { filter: brightness(.94); }
.btn--primary:focus-visible { outline-color: var(--amber-ink); }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--edge); }
.btn--ghost:hover { background: var(--panel); }

.btn--danger { background: transparent; color: var(--bad); border-color: var(--bad); }
.btn--danger:hover { background: var(--bad-bg); }

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

.btnRow { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* An action belonging to the whole section above it rather than to the last
   card in it. Without the space and the centring it sits flush against the
   grid and reads as part of the final card, which is the wrong thing
   entirely when the card is about defect photos and the button says "all
   the detail". */
.btnRow--section { justify-content: center; margin-top: 36px; }

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

.field { margin-bottom: 18px; }
.field label { display: block; font-weight: 600; font-size: .93rem; margin-bottom: 5px; }
.field .hint { display: block; color: var(--muted); font-size: .85rem; margin: -2px 0 6px; }

input, select, textarea {
  font: inherit;
  width: 100%;
  color: var(--ink);
  background: var(--page);
  border: 1px solid var(--edge);
  border-radius: 9px;
  padding: 11px 13px;
  min-height: 44px;
}
textarea { min-height: 130px; resize: vertical; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: 0; }

/* A field the browser or our own validation has rejected. The red border is
   backed by a message, never used alone: colour by itself is not a way to
   tell somebody something went wrong. */
input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"] {
  border-color: var(--bad);
  border-width: 2px;
}
.err { color: var(--bad); font-size: .88rem; font-weight: 600; margin: 5px 0 0; }

fieldset { border: 1px solid var(--hair); border-radius: var(--radius); padding: 16px 18px; margin: 0 0 18px; }
legend { font-weight: 700; padding: 0 6px; }

/* ---------------------------------------------------------------- *
 * Notices
 * ---------------------------------------------------------------- */

.note {
  border: 1px solid var(--hair);
  border-left: 4px solid var(--muted);
  background: var(--panel);
  border-radius: 8px;
  padding: 14px 18px;
  margin: 0 0 1.2em;
}
.note > :first-child { margin-top: 0; }
.note > :last-child { margin-bottom: 0; }
.note--ok { border-left-color: var(--ok); background: var(--ok-bg); }
.note--warn { border-left-color: var(--warn); background: var(--warn-bg); }
.note--bad { border-left-color: var(--bad); background: var(--bad-bg); }

/* ---------------------------------------------------------------- *
 * Tables
 *
 * A table on a phone is the classic cause of a page that scrolls sideways.
 * Wrapping it in .tableWrap keeps the scroll inside the table.
 * ---------------------------------------------------------------- */

.tableWrap { overflow-x: auto; margin-bottom: 1.2em; }
table { border-collapse: collapse; width: 100%; font-size: .95rem; }
caption { text-align: left; font-weight: 700; padding-bottom: .6em; }
th, td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--hair); }
th { font-weight: 700; }
thead th { border-bottom: 2px solid var(--edge); }

/* ---------------------------------------------------------------- *
 * Printing
 *
 * The legal pages get printed and filed. Make that produce something
 * readable rather than a screenshot of a website.
 * ---------------------------------------------------------------- */

@media print {
  .siteHeader, .siteFooter, .skip, .noPrint { display: none !important; }
  body { font-size: 11pt; color: #000; background: #fff; }
  a { color: #000; text-decoration: underline; }
  /* Printed pages lose the ability to click, so put the destination in
     the text where it can still be read. */
  .prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; }
  h2, h3 { break-after: avoid; }
  .card, .note { break-inside: avoid; }
}

/* ---------------------------------------------------------------- *
 * Reduced motion
 * ---------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
