/* Reset, typography and page frame. Shared by the technician app, the admin app and the portal.
 *
 * No colour, radius, shadow or motion literal may appear here or in any stylesheet except
 * tokens.css (R1-D24); tests/theme_test.php enforces that. Components live in blocks.css; each
 * screen's own file only arranges them.
 */

/* ---- Fonts (R1-D25) -----------------------------------------------------------------
 * Self-hosted, Latin subset, three files, 53 KB total. font-display: swap means text is
 * readable immediately in the fallback face and reflows once Plex arrives, which matters on
 * a weak signal on a roof. Licence: assets/fonts/LICENSE-IBM-Plex-OFL.txt.
 */
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/plex-sans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/plex-sans-600.woff2") format("woff2");
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/plex-mono-500.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  background: var(--paper);
  font-family: var(--font);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  /* Lining, tabular figures: measurements and times line up in a column. */
  font-variant-numeric: tabular-nums;
}

/* The technician app is read at arm's length on a phone, often in sunlight. */
body.tech { font-size: var(--text-md); }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: 0;   /* rule 6: no negative letter-spacing */
}
h1 { font-size: var(--text-xl); }
h2 { font-size: var(--text-lg); }
h3 { font-size: var(--text-md); }
h4 { font-size: var(--text-sm); }

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

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--brand-strong); }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
[hidden] { display: none !important; }

code, kbd, samp, pre, .mono { font-family: var(--font-mono); }

/* One focus treatment everywhere, including gloved taps that half-land on a control. */
:focus-visible {
  outline: var(--focus-width) solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* ---- Page frame ---------------------------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  height: 56px;
  padding: 0 var(--space-4);
  color: var(--panel);
  background: var(--ink);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: inherit;
  text-decoration: none;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}
.brand-mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  border-radius: var(--radius);
  color: var(--brand-ink);
  background: var(--brand);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.04em;
}
.brand-logo {
  max-height: 32px;
  max-width: 140px;
  object-fit: contain;
  background: var(--panel);
  border-radius: var(--radius);
  padding: var(--space-1);
}
.brand strong,
.brand small { display: block; }
.brand strong {
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brand small {
  font-size: var(--text-xs);
  /* The one place capitals are letter-spaced, besides table column headers. */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.72;
}
.topbar-actions { display: flex; align-items: center; gap: var(--space-2); flex: 0 0 auto; }

/* On a phone the company name, the logo and two buttons do not all fit. The brand gives way:
 * the strapline goes, the logo narrows, and the name ellipsises rather than overlapping the
 * buttons a technician needs to hit. */
@media (max-width: 560px) {
  .topbar { gap: var(--space-2); padding: 0 var(--space-2); }
  .brand { gap: var(--space-2); }
  .brand small { display: none; }
  .brand-logo { max-width: 88px; }
  .brand strong { font-size: var(--text-sm); }
}
/* When a logo is shown, the company name beside it is redundant on a phone, and truncating it to
 * one letter is worse than dropping it. Without a logo the name is all there is, so it stays. */
@media (max-width: 560px) {
  .brand-logo:not([hidden]) + span { display: none; }
}

.page-shell {
  max-width: 560px;
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) var(--space-7);
}

/* ---- The one signature (rule 10) -----------------------------------------------------
 * A tag ID or report number in the mono face inside a thin plate, echoing the QR sticker on
 * the equipment. Used identically in lists, headers, the portal and the public page. It is
 * the only decorative element the app has.
 */
.plate {
  display: inline-block;
  padding: 0 var(--space-2);
  border: var(--border) solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--panel);
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-weight: var(--weight-medium);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.muted { color: var(--muted); }
.center { text-align: center; }
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
