/*
 * QPI house style for the hosted pages.
 *
 * The same palette as stock.html and jobs.html, measured off qpiltd.co.uk:
 * navy #203758 for ink and table headings, the working blue #0265a7 for the
 * header bar and anything that points, #ededed as the page. Staff move between
 * these pages and the two apps all day, so they are deliberately the one look.
 *
 * A plain .css beside the pages rather than a <style> block in db.php: there
 * are eight pages sharing it, it is cached after the first request, and it is
 * uploaded by the same deploy as everything else in hosting/.
 *
 * No build step, no framework, no web font. Proxima Nova is declared and never
 * served on the live site, so this renders in Segoe UI exactly as qpiltd.co.uk
 * does, and nothing is fetched from a third party.
 */

:root {
  --navy: #203758;
  --navy-deep: #1f3554;
  --blue: #0265a7;
  --blue-bright: #0097ff;
  --paper: #ededed;

  --bg: #ededed;
  --surface: #ffffff;
  --surface-2: #f4f5f7;
  --border: rgba(32, 55, 88, .14);
  --ink: #203758;
  --ink-2: #3d4f6d;
  --ink-muted: #5e6f87;
  --accent: #0265a7;
  --good: #1d7850;
  --warn: #925e00;
  --bad: #a32b2b;
  --shadow: 0 1px 2px rgba(32, 55, 88, .06), 0 1px 3px rgba(32, 55, 88, .10);
  --zebra: rgba(237, 237, 237, .5);
  --on-accent: #ffffff;
}

/* Stepped down through the navy rather than inverted, so it is still the same
   brand. There is no switch on these pages - they follow the machine. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101b2b;
    --surface: #17253a;
    --surface-2: #1e2f48;
    --border: rgba(255, 255, 255, .15);
    --ink: #eaf0f7;
    --ink-2: #bccadb;
    --ink-muted: #8fa0b8;
    --accent: #4fc3ff;
    --good: #5cc98f;
    --warn: #d9a441;
    --bad: #e8736f;
    --shadow: none;
    --zebra: rgba(255, 255, 255, .045);
    --on-accent: #0d1a29;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.45 "proxima-nova", "Proxima Nova", -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  letter-spacing: -.01em;
}

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

/* ---------------------------------------------------------------- the bar */

.qpi-bar {
  background: var(--blue);
  color: #fff;
  padding: 10px clamp(16px, 3vw, 32px);
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.qpi-logo { display: flex; align-items: baseline; gap: 9px; flex: 0 0 auto; color: #fff; text-decoration: none; }
.qpi-logo-mark { font-size: 24px; font-weight: 700; letter-spacing: -.04em; line-height: 1; }
.qpi-logo-word { font-size: 10px; letter-spacing: .06em; opacity: .85; white-space: nowrap; }
.qpi-bar .spacer { flex: 1; }

/* Who you are and the way out. On the bar rather than in the page, because it
   is the same on every page and is not what anybody came to read. */
.qpi-who { font-size: 13px; color: rgba(255, 255, 255, .92); display: flex; align-items: center;
           gap: 10px; flex-wrap: wrap; }
.qpi-who a { color: #fff; text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, .5); }
.qpi-who a:hover { border-bottom-color: #fff; }
.qpi-who .sep { opacity: .55; }

/*
 * 1100px was right when these pages were forms and short reports. They are
 * tables now - the belt registers carry twelve columns of roll detail - and
 * 1100px was squeezing spec, location and price into a sideways scroll on a
 * screen with room to spare.
 *
 * The bar above already spans the full window, so a wide main is consistent
 * with it rather than a departure. Forms do not stretch: .card carries its own
 * 460px, so the sign-in stays the size it was.
 */
main { max-width: 1800px; margin: 0 auto; padding: 24px clamp(16px, 3vw, 32px) 56px; }

/*
 * Prose does not get the full 1800px. A line of text that long is genuinely
 * hard to read - the eye loses the start of the next line - so anything meant
 * to be read rather than scanned is capped at a sane measure. Tables are
 * scanned, not read, and keep the whole width.
 */
.lede, p.note, .info-box, .warn, .bad-box { max-width: 90ch; }

h1 { font-size: clamp(24px, 2vw, 32px); font-weight: 500; letter-spacing: -.03em; margin: 0 0 18px; }
h2 { font-size: 19px; font-weight: 600; letter-spacing: -.02em; margin: 32px 0 10px; }

/* ------------------------------------------------------------------ tables */

table {
  border-collapse: collapse;
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  font-size: 13.5px;
  box-shadow: var(--shadow);
}
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }
th {
  background: var(--navy);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  border-bottom: 2px solid var(--blue);
}
tbody tr:nth-child(even) { background: var(--zebra); }
tbody tr:last-child td { border-bottom: none; }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
tr.off { opacity: .55; }

/* Wide tables get their own scrollbar rather than pushing the page sideways. */
.scroller { overflow-x: auto; }

.ok { color: var(--good); font-weight: 600; }
.bad { color: var(--bad); font-weight: 600; }
.na { color: var(--ink-muted); }
.note { color: var(--ink-muted); font-size: 13px; }

code { background: var(--surface-2); border: 1px solid var(--border); padding: 1px 5px; border-radius: 4px; }

/* ------------------------------------------------------------------- boxes
   An aside is information and takes the working blue; amber is caution; red is
   kept for something that actually went wrong. On this brand the warm colours
   are status and never decoration. */

.info-box, .warn, .bad-box {
  border-radius: 6px;
  padding: 12px 14px;
  font-size: 13.5px;
  margin: 16px 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  background: var(--surface-2);
}
.warn { background: rgba(146, 94, 0, .07); border-color: rgba(146, 94, 0, .22); border-left-color: var(--warn); }
.bad-box { background: rgba(163, 43, 43, .07); border-color: rgba(163, 43, 43, .22); border-left-color: var(--bad); }

/* ----------------------------------------------------------------- buttons
   The site's buttons fill from the left on hover. overflow:hidden is
   load-bearing: the wipe waits at translateX(-101%), which without it is a
   solid rectangle parked alongside the button. */

.btn, a.btn, button {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  font: inherit;
  font-weight: 600;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 14px;
  min-height: 34px;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: color .25s ease, border-color .25s ease, transform .25s ease;
}
.btn::before, a.btn::before, button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--navy);
  transform: translateX(-101%);
  transition: transform .4s cubic-bezier(.22, 1, .36, 1);
}
.btn:hover, a.btn:hover, button:hover { color: #fff; border-color: var(--navy); transform: translateY(-1px); }
.btn:hover::before, a.btn:hover::before, button:hover::before,
.btn:focus-visible::before, a.btn:focus-visible::before, button:focus-visible::before { transform: translateX(0); }

.btn-primary, a.btn-primary, button.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.btn-primary::before { background: var(--navy-deep); }
.btn-primary:hover, .btn-primary:focus-visible { color: #fff; border-color: var(--navy-deep); }

/* A row of small actions against a table row. */
.rowactions { display: flex; gap: 6px; flex-wrap: wrap; }
.rowactions button { font-size: 12.5px; padding: 4px 9px; min-height: 28px; }

/* ------------------------------------------------------------------- forms */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 22px;
  max-width: 460px;
}
.card--wide { max-width: 620px; }

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }
.field input, .field select {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 9px 10px;
}
.field .note { display: block; margin-top: 4px; }

input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The one place the bright blue earns its keep on a light background. */
button:focus-visible, a:focus-visible { outline: 2px solid var(--blue-bright); outline-offset: 2px; }

/* The password shown exactly once. It gets read down a phone line, so it is
   set large and spaced rather than dropped into the running text. */
.oncepw {
  display: inline-block;
  font-size: 21px;
  letter-spacing: .06em;
  font-weight: 700;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 12px;
  margin: 4px 0;
}

@media (prefers-reduced-motion: reduce) {
  .btn, a.btn, button, .btn::before, a.btn::before, button::before { transition: none; }
  .btn:hover, a.btn:hover, button:hover { transform: none; }
}

/* The characters the encoding check displays one per row - the yuan sign, the
   en dash, the curly quotes. Set larger than the running text because the
   whole point is to look at the glyph and see it is intact.
   A class rather than an inline style="": the Content-Security-Policy allows
   no inline style at all, so an attribute here would simply not apply. */
td.glyph { font-size: 18px; }

/* ===================================================================
   Stock screens (Phase 4)

   Everything below is a class rather than an inline style, because the
   Content-Security-Policy on these pages allows no inline style at all.
   That is a deliberate constraint, not an obstacle: it is what lets the
   policy stay tight enough to be worth having.
   =================================================================== */

/* The filter bar above the product list. Wraps to one control per line on a
   phone rather than scrolling sideways - staff will open this on a phone long
   before the field app exists. */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  box-shadow: var(--shadow);
  margin-bottom: 14px;
}
.filters .field { margin-bottom: 0; }
.filters .field input[type="search"] { min-width: min(320px, 70vw); }
.filters .field--check { padding-bottom: 7px; }
.filters .field--check label { font-weight: 500; display: flex; align-items: center; gap: 6px; }
.filters .field--go { margin-left: auto; display: flex; gap: 8px; }

/* Sortable column headings. The heading is already navy on white, so the link
   inherits rather than turning the usual blue - a table of blue headings reads
   as a mistake. */
th a { color: inherit; text-decoration: none; border-bottom: 1px dotted rgba(255, 255, 255, .45); }
th a:hover { border-bottom-style: solid; }
.sortmark { font-size: 9px; opacity: .8; }

/* A second line inside a cell: the part number under the product name, or how
   much a recorded entry has moved the figure. */
.sub { display: block; font-size: 12px; color: var(--ink-muted); font-weight: 400; }
td.num .sub { font-variant-numeric: tabular-nums; }

/* Where you are, above the page heading. */
.crumbs { font-size: 13px; color: var(--ink-muted); margin: -6px 0 14px; }
.crumbs a { color: var(--accent); }

.lede { font-size: 17px; color: var(--ink-2); margin: 0 0 18px; }

/* The handful of figures somebody actually came to the page for. */
.tiles { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 18px; }
.tile {
  flex: 1 1 150px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  box-shadow: var(--shadow);
}
.tile-n { display: block; font-size: 24px; font-weight: 600; letter-spacing: -.02em; color: var(--ink); }
.tile-l { display: block; font-size: 12px; color: var(--ink-muted); margin-top: 2px; }

/* The row count beside a section heading. */
.count { font-size: 13px; font-weight: 400; color: var(--ink-muted); }

.pager { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 14px 0 4px; }
.pager-where { font-size: 13px; color: var(--ink-muted); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- signing in with Microsoft

   The work-account button leads, because it is what nearly everybody will use.
   The password form below it is the way in when Microsoft cannot be reached,
   so it is present and plain rather than hidden behind a link. */
.card--signin { padding-bottom: 18px; }

.or {
  max-width: 460px;
  margin: 14px 0;
  text-align: center;
  color: var(--ink-muted);
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.or::before, .or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* The Microsoft mark, drawn in CSS rather than fetched. Four squares in their
   brand colours - nothing is loaded from a third party, which keeps the
   Content-Security-Policy as tight as it is and means the button still looks
   right on a machine with no internet beyond this site. */
.btn-ms { display: inline-flex; align-items: center; gap: 10px; }
.btn-ms::after {
  content: "";
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  background:
    linear-gradient(to right, #f25022 0 7px, transparent 7px 9px, #7fba00 9px 16px) top / 16px 7px no-repeat,
    linear-gradient(to right, #00a4ef 0 7px, transparent 7px 9px, #ffb900 9px 16px) bottom / 16px 7px no-repeat;
}
