/* The portal's look.
 *
 * The palette is the testing report's :root, unchanged, so the portal, the
 * report and the app read as one product. It is also built narrow-first: a
 * technician checking what they have been given will do it on a phone, and the
 * plan is explicit that the phone is a browser and never a second codebase.
 */

:root {
  --navy: #0f172a;
  --accent: #C8102E;
  --accent2: #a50d26;
  --ink: #1e293b;
  --ink2: #64748b;
  --line: #e2e8f0;
  --line2: #cbd5e1;
  --pale: #f1f5f9;
  --bg: #f8fafc;
  --ok: #16a34a;
  --warn: #d97706;
  --bad: #dc2626;
  --mono: "Cascadia Mono", ui-monospace, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 "Segoe UI", Arial, sans-serif;
}

/* ---- chrome ------------------------------------------------------------- */

header { background: #fff; border-bottom: 1px solid var(--line); }

.bar {
  max-width: 1000px;
  margin: 0 auto;
  padding: 12px 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: center;
}

/* The same lockup the exe and the testing report use: the real flame badge
   out of the app (hyperpyre_mark.png), then the wordmark as TEXT with a red H
   and F. The app's own wordmark PNG is not used because its "yper" and "ire"
   are near-white for the app's dark sidebar and would vanish on white - the
   report hit this in v1.58 and solved it the same way.
   The image URL is relative, so it resolves against wherever this stylesheet
   is served from and does not need to know the base path. */
.brand {
  display: inline-flex; align-items: center; gap: 9px;
  text-decoration: none; color: var(--navy);
  font-size: 1.2rem; font-weight: 800; letter-spacing: .005em;
}
.brand b { color: var(--accent); font-weight: 800; }
.brand .mark {
  height: 1.15em; width: 1.15em; flex: 0 0 auto; border-radius: 24%;
  background: url(hyperpyre-mark.png) center / contain no-repeat;
}

/* The customer's mark, beside HyperPyre's own. Capped hard in height so a
   tall logo cannot push the header about, and given a divider so the two
   marks read as two things rather than one muddle. */
.cosep { width: 1px; height: 22px; background: var(--line2); }
.cologo { max-height: 26px; max-width: 150px; object-fit: contain; display: block; }

.logobox { display: flex; gap: 14px; align-items: center; margin: 0 0 12px; }
.logoprev {
  max-height: 60px; max-width: 220px; object-fit: contain;
  border: 1px solid var(--line); border-radius: 8px; padding: 6px; background: #fff;
}
.logometa { font-size: .82rem; color: var(--ink2); }
.logonone {
  margin: 0 0 12px; padding: 12px; border: 1px dashed var(--line2);
  border-radius: 8px; color: var(--ink2); font-size: .88rem;
}
.problemtext { color: var(--bad); }
.tagline { font-style: italic; }

.nav { margin-left: auto; display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; font-size: .9rem; }
.nav a { color: var(--ink2); text-decoration: none; padding: 4px 2px; border-bottom: 2px solid transparent; }
.nav a:hover { color: var(--navy); }
.nav a.on { color: var(--navy); border-bottom-color: var(--accent); font-weight: 600; }
.nav .who { color: var(--ink2); font-size: .82rem; }
.inline { display: inline; margin: 0; }

main { max-width: 1000px; margin: 0 auto; padding: 18px 16px 70px; }

.eyebrow {
  font-size: .7rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent); font-weight: 700; margin: 0;
}
h1 { margin: 2px 0 14px; font-size: 1.4rem; color: var(--navy); }
h2 { font-size: 1.05rem; color: var(--navy); margin: 0 0 10px; }

/* ---- messages ----------------------------------------------------------- */

.said, .problem {
  margin: 0 0 14px; padding: 9px 12px; border-radius: 8px;
  border: 1px solid var(--line2); background: #fff; font-size: .92rem;
}
.said { border-color: #bbf7d0; background: #f0fdf4; color: #14532d; }
.problem { border-color: #fecaca; background: #fef2f2; color: #7f1d1d; }
.ok { color: #14532d; }
.warn { color: var(--warn); }
.dim { color: var(--ink2); }
.mono { font-family: var(--mono); font-size: .88em; }
.meta { color: var(--ink2); font-size: .85rem; }
.note {
  margin: 0 0 14px; padding: 10px 12px; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: 8px;
}

/* Where the subscription stands. Never a modal and never a blocker: at worst
   the account is read-only, and the technician's job still has to be openable. */
.account {
  margin: 0 0 14px; padding: 8px 12px; border-radius: 8px;
  font-size: .85rem; border: 1px solid var(--line2); background: #fff;
}
.account.info { border-color: #bfdbfe; background: #eff6ff; color: #1e3a8a; }
.account.warn { border-color: #fde68a; background: #fffbeb; color: #92400e; }
.account.stop { border-color: #fecaca; background: #fef2f2; color: #7f1d1d; }

/* ---- cards and forms ---------------------------------------------------- */

.card {
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  padding: 16px; margin: 0 0 16px;
}
.card.narrow { max-width: 520px; }
.card.collect { border-color: var(--line2); background: #fff; }

fieldset { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; margin: 0 0 14px; }
legend { padding: 0 6px; font-weight: 600; color: var(--navy); font-size: .9rem; }

label { display: block; margin: 0 0 12px; font-size: .85rem; color: var(--ink2); }
input, select, textarea {
  display: block; width: 100%; margin-top: 4px; padding: 9px 10px;
  font: inherit; color: var(--ink); background: #fff;
  border: 1px solid var(--line2); border-radius: 8px;
}
input[type="file"] { padding: 8px; background: var(--pale); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--navy); outline-offset: 1px; }

.row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin: 0 0 12px; }
.row label { margin: 0; flex: 1 1 200px; }
.row.tight { margin: 0; gap: 6px; align-items: center; }
.row.tight input { width: auto; min-width: 150px; margin: 0; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin: 14px 0 0; }

.btn {
  display: inline-block; padding: 10px 16px; border: 0; border-radius: 8px;
  background: var(--accent); color: #fff; font: inherit; font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.btn:hover { background: var(--accent2); }
.btn:disabled { background: var(--line2); cursor: default; }
.btn.small { padding: 6px 11px; font-size: .86rem; }
.btn.ghost { background: #fff; color: var(--navy); border: 1px solid var(--line2); }
.btn.ghost:hover { background: var(--pale); }
.btn.danger { background: #fff; color: var(--bad); border: 1px solid #fecaca; }
.btn.danger:hover { background: #fef2f2; }

.linky {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--ink2); text-decoration: underline; cursor: pointer;
}
.linky:hover { color: var(--navy); }

hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }

/* ---- filtering ---------------------------------------------------------- */

.tabs {
  display: flex; flex-wrap: wrap; gap: 4px;
  border-bottom: 1px solid var(--line); margin: 0 0 12px;
}
.tab {
  padding: 8px 12px; text-decoration: none; color: var(--ink2);
  border-bottom: 2px solid transparent; font-size: .9rem; white-space: nowrap;
}
.tab:hover { color: var(--navy); }
.tab.on { color: var(--navy); border-bottom-color: var(--accent); font-weight: 600; }
.tally {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  background: var(--pale); color: var(--ink2); font-size: .74rem; font-weight: 600;
}
.tally.bad { background: #fee2e2; color: #991b1b; }
.tally.none { background: transparent; color: var(--line2); }

.filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 14px; }
.filters input, .filters select { width: auto; margin: 0; padding: 7px 10px; font-size: .9rem; }
.filters input[type="search"] { min-width: 210px; flex: 1 1 210px; }

/* The job code. Big, monospaced and spaced out, because it gets read down a
   phone to somebody standing at a panel. */
.codebox { margin: 0 0 6px; }
.codelabel {
  font-size: .7rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink2); font-weight: 700;
}
.code {
  font-family: var(--mono); font-size: 1.7rem; font-weight: 700;
  letter-spacing: .14em; color: var(--navy); margin: 2px 0 8px;
}
/* The two-step QR code: always black on white with its quiet zone, which is
   what a phone camera reads. */
.qr { margin: 4px 0 12px; line-height: 0; }
.qr svg { max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 6px; }
.qrkey summary { cursor: pointer; color: var(--navy); font-size: .9rem; }
/* A two-step setup key is 32 characters: smaller, and allowed to wrap. */
#totpkey { font-size: 1.15rem; letter-spacing: .08em; overflow-wrap: anywhere; }
/* Recovery codes, to be written down or printed. */
.codes { font-size: 1.05rem; line-height: 1.7; background: var(--pale); padding: 10px 14px; margin: 0 0 12px; }

.count { margin: 0 0 8px; }
/* Controls inside a table cell stay the size of their content, or a select
   stretches the column and the table stops reading as a table. */
.grid td .row.tight select,
.grid td .row.tight input { width: auto; min-width: 104px; max-width: 160px; }
.grid td .row.tight { gap: 5px; margin-top: 4px; }

label.tick { display: flex; gap: 9px; align-items: center; color: var(--ink); font-size: .92rem; }

/* A tick to be on the job, a dot to lead it. */
.crew { display: grid; gap: 2px; margin: 0 0 10px; }
.crewrow {
  display: flex; gap: 14px; align-items: center; justify-content: space-between;
  padding: 5px 8px; border-radius: 7px;
}
.crewrow:hover { background: var(--pale); }
.crewrow label.tick { margin: 0; }
.crewrow label.tick.lead { color: var(--ink2); font-size: .82rem; flex: 0 0 auto; }
fieldset.inner { margin: 0 0 12px; background: #fff; }
label.tick input { width: auto; margin: 0; }
.late { color: var(--bad); }
.soon { color: var(--warn); }

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

.grid { width: 100%; border-collapse: collapse; background: #fff; margin: 0 0 16px; }
.grid th, .grid td {
  text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.grid thead th {
  font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink2); background: var(--pale); border-bottom: 1px solid var(--line2);
}
.grid td small { display: block; color: var(--ink2); }
.grid .num, .grid th.num { text-align: right; font-variant-numeric: tabular-nums; }
.grid.tight th, .grid.tight td { padding: 6px 10px; font-size: .88rem; }
.grid a { color: var(--navy); }
.grid tr.off td:not(.menucell) { opacity: .55; }   /* the menu stays readable: Restore lives there */

.facts { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0 0 16px; }
.facts dt { color: var(--ink2); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; padding-top: 2px; }
.facts dd { margin: 0; }

/* The ⋯ on a row: everything that can be done to it, out of sight until asked
   for. It opens a window in the middle of the screen (ShootC, 2026-09-24: the
   old drop-down had to be scrolled and closed from the same ⋯). */
.menucell { width: 1%; text-align: right; white-space: nowrap; }
.menubtn {
  display: inline-block; cursor: pointer; padding: 2px 10px; border: 1px solid var(--line2);
  border-radius: 6px; color: var(--ink2); font-weight: 700; letter-spacing: 1px; background: #fff;
  font: inherit; line-height: 1.5;
}
.menubtn:hover { background: var(--pale); color: var(--navy); }

/* A window: one job at a time, Save or Close. The browser's own <dialog>, so
   Esc closes it and the page behind cannot be clicked by accident. */
dialog.win {
  width: min(480px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 0;
  border: 1px solid var(--line2); border-radius: 10px; background: #fff; color: var(--ink);
  box-shadow: 0 18px 50px rgba(15, 23, 42, .25); text-align: left; white-space: normal;
}
dialog.win::backdrop { background: rgba(15, 23, 42, .38); }
.winhead {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
}
.winhead h2 { margin: 0; font-size: 1.05rem; }
.winx { background: none; border: 0; font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--ink2); padding: 0 4px; }
.winx:hover { color: var(--navy); }
.winbody { padding: 14px 18px 16px; }
.winbody label { margin: 0 0 10px; }
.winbody input:not([type="checkbox"]):not([type="radio"]), .winbody select, .winbody textarea { width: 100%; }
.winbody .meta { margin: 0 0 10px; }
.winfoot { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }
/* The ⋯ window's list of what can be done. */
.actions-list { display: flex; flex-direction: column; gap: 6px; }
.actions-list button {
  text-align: left; padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px;
  background: #fff; cursor: pointer; font: inherit; color: var(--navy);
}
.actions-list button:hover { background: var(--pale); }
.actions-list button.danger { color: var(--accent); }
.actions-list small { display: block; color: var(--ink2); font-size: .8rem; }
/* A button that opens a window, sitting where the open form used to. */
.opens { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 16px; }
.opens .filters { margin: 0; }
.former summary { cursor: pointer; }
.former table { margin-top: 10px; }

.legend { margin: 0 0 16px; font-size: .9rem; }
.legend summary { cursor: pointer; color: var(--ink2); }
.legend dl { display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; margin: 10px 0 0; }
.legend dt { font-family: var(--mono); color: var(--navy); }
.legend dd { margin: 0; color: var(--ink2); }

.preview { margin-top: 12px; padding: 12px; background: var(--pale); border-radius: 10px; }
.preview .grid { margin: 0; }

.chip {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: .76rem; font-weight: 600; letter-spacing: .02em;
}
.chip.grey  { background: var(--pale);  color: var(--ink2); }
.chip.blue  { background: #e0e7ff;      color: #3730a3; }
.chip.amber { background: #fef3c7;      color: #92400e; }
.chip.green { background: #dcfce7;      color: #14532d; }

ol { padding-left: 20px; }
ol li { margin: 0 0 6px; }

/* ---- the phone ---------------------------------------------------------- */
/* A technician checks what they have been given standing next to a van. The
   table has to survive that, so on a narrow screen the columns that are only
   context stand down and the rows become cards. */

@media (max-width: 640px) {
  .bar { padding: 10px 14px; }
  main { padding: 14px 14px 60px; }
  .facts { grid-template-columns: 1fr; gap: 2px; }
  .facts dd { margin: 0 0 8px; }

  .grid, .grid tbody, .grid tr, .grid td { display: block; width: 100%; }
  .grid thead { display: none; }
  .grid tr {
    border: 1px solid var(--line); border-radius: 10px;
    margin: 0 0 10px; padding: 4px 0;
  }
  .grid td { border: 0; padding: 5px 12px; }
  .grid .num { text-align: left; }

  /* The head row is gone, so each value carries its own label. */
  .grid td[data-label]::before {
    content: attr(data-label);
    display: inline-block;
    min-width: 86px;
    color: var(--ink2);
    font-size: .72rem;
    letter-spacing: .08em;
    text-transform: uppercase;
  }

  .row.tight input { width: 100%; min-width: 0; }
  .filters { gap: 6px; }
  .filters input, .filters select, .filters button { width: 100%; }
  .tabs { gap: 0; }
  .tab { padding: 8px 10px; font-size: .86rem; }
  .btn { padding: 12px 16px; }          /* a thumb, not a mouse */
  /* (the old drop-down menu lived here; windows need nothing for phone width) */
  .menucell { width: auto; text-align: left; }
}
