/* ============================================================================
   printer.wemakerobots.com — owner portal
   Light theme. Archivo for voice, IBM Plex Mono for machine values.
   Amber (the Form 3's UV cover) is signal only, never small text.
   ========================================================================= */

/* --- Fonts ------------------------------------------------------------- */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/archivo-latin.92895abae7c5.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/archivo-latin-ext.288d2a1c9f04.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/plex-mono-400-latin.814fe1615d4d.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/plex-mono-400-latin-ext.17a5b2a15bf5.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/plex-mono-500-latin.6708425c446b.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/plex-mono-500-latin-ext.216ee1a35b06.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Tokens ------------------------------------------------------------ */

:root {
  color-scheme: light;

  --bg: #f3f4f6;
  --paper: #ffffff;
  --ink: #14171b;
  --ink-muted: #626b76;
  --rule: #dfe2e6;
  --rule-strong: #c6cbd2;

  --amber: #e8a21c;
  --amber-text: #9a6400; /* amber legible as text; the raw amber is fills only */
  --amber-wash: #fdf3de;
  --green: #0f7b5a;
  --danger: #b4232b;

  --sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --content: 1040px;
  --measure: 62ch;
  --radius: 4px;
  --radius-sm: 3px;
  --shadow: 0 1px 2px rgba(20, 23, 27, .04), 0 10px 30px -18px rgba(20, 23, 27, .3);

  font-family: var(--sans);
}

/* --- Base -------------------------------------------------------------- */

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 400 1rem/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
}

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  transition: text-decoration-color .14s ease;
}
a:hover { text-decoration-color: var(--amber); text-decoration-thickness: 2px; }

.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
/* Mono runs inside prose are things like key fingerprints: one long token with nowhere
   natural to break, which pushes the whole page sideways on a phone if left alone. */
p .mono { overflow-wrap: anywhere; }

.muted, .note, .help { color: var(--ink-muted); }

h1 {
  font-size: 1.85rem;
  font-weight: 600;
  letter-spacing: -.025em;
  line-height: 1.18;
  margin: 0 0 .35rem;
}

/* Section headings are a label rail: mono tag, hairline to the right edge. */
h2 {
  display: flex;
  align-items: center;
  gap: .95rem;
  font: 500 .72rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-muted);
  margin: 2.6rem 0 1rem;
}
h2::after { content: ""; flex: 1; height: 1px; background: var(--rule); }

main p { max-width: var(--measure); }
main .modal p, main .qmap p, main td p { max-width: none; }

/* --- Masthead + footer ------------------------------------------------- */

.site-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .6rem 1.5rem;
  padding: 1.05rem 1.6rem;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.brand {
  font: 500 .92rem/1 var(--mono);
  letter-spacing: -.02em;
  color: var(--ink);
  text-decoration: none;
}
.brand span { color: var(--ink-muted); font-weight: 400; }
.brand:hover { text-decoration: none; }

.site-header nav { display: flex; align-items: baseline; gap: 1.4rem; }
.site-header nav a, .linklike {
  font: 500 .7rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-muted);
  text-decoration: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.site-header nav a:hover, .linklike:hover { color: var(--ink); text-decoration: none; }
.inline-form { display: inline; margin: 0; }

.content {
  flex: 1;
  width: 100%;
  max-width: var(--content);
  margin: 2.6rem auto 4rem;
  padding: 0 1.6rem;
}

.site-footer {
  width: 100%;
  max-width: var(--content);
  margin: 0 auto;
  padding: 1.25rem 1.6rem 2.6rem;
  border-top: 1px solid var(--rule);
  font: 400 .72rem/1.6 var(--mono);
  letter-spacing: .03em;
  color: var(--ink-muted);
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  padding: .58rem 1rem;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--paper);
  font: 500 .93rem/1.25 var(--sans);
  text-decoration: none;
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.btn:hover { background: #000; border-color: #000; color: var(--paper); text-decoration: none; }
/* .btn sets display, which would override the UA [hidden] rule; restore it explicitly
   (higher specificity) so hidden nav buttons actually hide. */
.btn[hidden] { display: none; }
.btn[disabled], .btn[disabled]:hover {
  cursor: not-allowed;
  background: var(--rule);
  border-color: var(--rule);
  color: var(--ink-muted);
}
.btn-secondary[disabled], .btn-secondary[disabled]:hover {
  background: var(--paper);
  border-color: var(--rule);
  color: var(--rule-strong);
}

.btn-secondary, .btn-google {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--rule-strong);
}
.btn-secondary:hover, .btn-google:hover {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--ink);
}
.btn-danger {
  background: var(--paper);
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 40%, var(--rule));
}
.btn-danger:hover { background: var(--danger); border-color: var(--danger); color: var(--paper); }
.btn-block { display: flex; width: 100%; padding: .7rem 1rem; }

.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  padding-bottom: 1.2rem;
  border-bottom: 1px solid var(--rule);
}
.page-head h1 { margin: 0; }
.page-head .subtitle { margin: .35rem 0 0; color: var(--ink-muted); font-size: .95rem; }
.page-head .subtitle .status { margin-left: .6rem; vertical-align: baseline; }
.actions { display: flex; flex-wrap: wrap; gap: .5rem; }

/* --- Messages ---------------------------------------------------------- */

.messages { list-style: none; padding: 0; margin: 0 0 1.8rem; display: grid; gap: .5rem; }
.msg {
  padding: .7rem .9rem .7rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule-strong);
  border-radius: var(--radius);
  font-size: .94rem;
}
.msg.success { border-left-color: var(--green); }
.msg.error { border-left-color: var(--danger); }

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

.stack { display: flex; flex-direction: column; gap: 1.2rem; max-width: 620px; }
.field { display: flex; flex-direction: column; gap: .35rem; }
.field > label { font-weight: 500; font-size: .9rem; }
.field input, .field select, .field textarea {
  width: 100%;
  padding: .58rem .7rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.field textarea { min-height: 6.5rem; font-family: var(--mono); font-size: .84rem; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--amber);
  box-shadow: 0 0 0 3px var(--amber-wash);
}
.field input[type="file"] { padding: .45rem .5rem; font-size: .9rem; }

/* Django's ClearableFileInput emits loose "Currently:"/"Change:" text, a clear checkbox
   and a <br> as siblings. In a column flex each lands on its own row and the checkbox
   centres itself; reflow the whole group into one tidy wrapped line instead. */
.field:has(input[type="file"]) {
  flex-flow: row wrap;
  align-items: center;
  gap: .3rem .45rem;
  font-size: .85rem;
  color: var(--ink-muted);
}
.field:has(input[type="file"]) > input[type="file"],
.field:has(input[type="file"]) > .help,
.field:has(input[type="file"]) > .error { flex: 1 0 100%; }
.field:has(input[type="file"]) > label:first-of-type {
  flex: 1 0 100%;
  color: var(--ink);
  font-size: .9rem;
}
/* the "Clear" label the widget emits next to its checkbox */
.field:has(input[type="file"]) > label:not(:first-of-type) { font-weight: 400; font-size: .85rem; }
.field:has(input[type="file"]) br { display: none; }
.field > input[type="checkbox"] { width: auto; align-self: center; margin: 0 0 0 .25rem; }
.field.has-error input, .field.has-error select, .field.has-error textarea {
  border-color: var(--danger);
}
.error { color: var(--danger); font-size: .85rem; }
.field .help, .help { color: var(--ink-muted); font-size: .84rem; line-height: 1.55; }
.field .help ul { margin: .35rem 0 0; padding-left: 1.1rem; }
.field .help li { margin: .12rem 0; }

.checkbox, .field-check { display: flex; gap: .6rem; align-items: flex-start; font-weight: 400; }
.checkbox input, .field-check input { width: auto; margin-top: .25rem; accent-color: var(--ink); }
.field-check label { font-weight: 400; font-size: .9rem; color: var(--ink-muted); }

/* Ownership attestation reads as a deliberate act, not another field. */
.attest {
  background: var(--amber-wash);
  border: 1px solid color-mix(in srgb, var(--amber) 35%, var(--rule));
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  font-size: .92rem;
}
.attest .checkbox input { accent-color: var(--amber-text); }

/* --- Printer roster ---------------------------------------------------- */

.card-grid {
  list-style: none;
  padding: 0;
  margin: 1.6rem 0 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
}
.card {
  display: flex;
  flex-direction: column;
  gap: .22rem;
  padding: 1.15rem 1.2rem 1.05rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.card:hover { border-color: var(--ink); box-shadow: var(--shadow); }
.card-title {
  font-size: 1.08rem;
  font-weight: 600;
  letter-spacing: -.015em;
  text-decoration: none;
}
.card-title:hover { text-decoration: underline; text-decoration-color: var(--amber); }
.card-meta { color: var(--ink-muted); font-size: .88rem; }
.card-meta.mono { font-size: .78rem; }
.card .status { margin-top: .85rem; }

/* Square swatch + plain-case mono label. Pills read as framework default. */
.status {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font: 400 .74rem/1.3 var(--mono);
  color: var(--ink-muted);
}
.status::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  background: var(--rule-strong);
}
.status-anchored { color: var(--green); }
.status-anchored::before { background: var(--green); }
.status-pending { color: var(--amber-text); }
.status-pending::before { background: var(--amber); }
.status-failed { color: var(--danger); }
.status-failed::before { background: var(--danger); }

.empty {
  margin: 2.5rem 0 0;
  padding: 2.2rem 1.5rem;
  text-align: center;
  border: 1px dashed var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink-muted);
}
.empty p { margin: 0 auto 1.1rem; max-width: 40ch; }

/* --- Detail: data sheet + action rail ---------------------------------- */

.sheet {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 296px;
  gap: 2.8rem;
  align-items: start;
  margin-top: 1.9rem;
}
.sheet-main { min-width: 0; }
.sheet-main > h2:first-child { margin-top: 0; }
.sheet-rail { position: sticky; top: 1.6rem; display: grid; gap: 1rem; }

.detail {
  display: grid;
  grid-template-columns: 152px minmax(0, 1fr);
  margin: 0;
  border-top: 1px solid var(--rule);
}
.detail dt {
  font: 500 .68rem/1.5 var(--mono);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-muted);
  padding: .8rem 1rem .8rem 0;
  border-bottom: 1px solid var(--rule);
}
.detail dd {
  margin: 0;
  padding: .75rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: .95rem;
}

.keybox {
  margin: 0;
  padding: .85rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow-x: auto;
  font: 400 .78rem/1.65 var(--mono);
  white-space: pre-wrap;
  word-break: break-all;
}

.panel {
  padding: 1.15rem 1.2rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.panel h3 {
  margin: 0 0 .8rem;
  font: 500 .68rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-muted);
}
.panel p { font-size: .87rem; }
.panel-danger { border-color: color-mix(in srgb, var(--danger) 32%, var(--rule)); }
.confirm { max-width: 620px; }
.confirm p { margin: 0; font-size: .95rem; max-width: 58ch; }
.confirm .actions { margin-top: 1.3rem; }
.form-panel { display: flex; flex-direction: column; gap: 1.3rem; padding: 1.4rem 1.5rem 1.5rem; }
/* Inset rather than a real border so the panel geometry stays identical across states. */
.panel--active { box-shadow: inset 3px 0 0 var(--amber); }
.panel--done { box-shadow: inset 3px 0 0 var(--green); }
.panel--failed { box-shadow: inset 3px 0 0 var(--danger); }
.panel-actions { display: grid; gap: .5rem; margin: 1.1rem 0 0; }
.panel-actions .btn { width: 100%; }

/* --- QSPI address map (the signature) ---------------------------------- */

.qmap { margin: 0; }
.qmap-head {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  margin-bottom: .8rem;
  font: 500 .68rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-muted);
}
.qmap-head b { color: var(--ink); font-weight: 500; }

.qmap-body { position: relative; padding-bottom: 180px; }

/* 16 graduations = 256 KiB each, so the ruler means something. background-size
   repeats exactly; percentage stops inside repeating-linear-gradient drift. */
.qmap-strip {
  position: relative;
  height: 15px;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background-color: var(--paper);
  background-image: linear-gradient(90deg, var(--rule) 1px, transparent 1px);
  background-size: 6.25% 100%;
  overflow: hidden;
}
.qmap-tick {
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: var(--at);
  width: 3px;
  background: var(--ink);
}

.qmap-axis {
  display: flex;
  justify-content: space-between;
  margin-top: .45rem;
  font: 400 .68rem/1 var(--mono);
  letter-spacing: .02em;
  color: var(--ink-muted);
}

.qmap-marks { list-style: none; margin: 0; padding: 0; }
.qmap-mark {
  position: absolute;
  left: var(--at);
  top: var(--top);
  padding-left: .6rem;
  max-width: 27ch;
}
.qmap-mark::before {
  content: "";
  position: absolute;
  left: 0;
  bottom: calc(100% - .35rem);
  width: 1px;
  height: var(--lead);
  background: var(--rule-strong);
}
.qmap-mark b {
  display: block;
  font: 500 .76rem/1.4 var(--mono);
  letter-spacing: -.01em;
  color: var(--ink);
}
.qmap-mark span { display: block; font-size: .78rem; color: var(--ink-muted); }
.qmap-mark em {
  display: block;
  margin-top: .1rem;
  font-style: normal;
  font-size: .78rem;
  color: var(--ink);
}
/* The rightmost callout takes the near tier, so no leader line ever crosses a label. */
.qmap-mark--key { --top: 44px; --lead: 30px; }
.qmap-mark--env { --top: 122px; --lead: 108px; }

/* Nothing uploaded yet: the whole instrument is unpowered. */
.qmap--blank .qmap-strip { border-color: var(--rule-strong); }
.qmap--blank .qmap-tick { background: var(--rule-strong); }
.qmap--blank .qmap-mark b,
.qmap--blank .qmap-mark em { color: var(--ink-muted); }

/* Building: a write pass sweeps the address space, key region lit. */
.qmap--writing .qmap-strip::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 22%;
  background: linear-gradient(90deg, transparent, var(--amber-wash) 45%, var(--amber));
  animation: qsweep 1.9s linear infinite;
}
@keyframes qsweep {
  from { transform: translateX(-100%); }
  to { transform: translateX(455%); }
}
.qmap--writing .qmap-tick--key,
.qmap--done .qmap-tick--key { background: var(--amber); width: 4px; }
.qmap--writing .qmap-mark--key em,
.qmap--done .qmap-mark--key em { color: var(--amber-text); font-weight: 500; }
.qmap--done .qmap-mark--key em::after { content: " ✓"; color: var(--green); }

/* --- A/B system partition ---------------------------------------------- */

.ab-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  max-width: 420px;
  margin: .9rem 0 .8rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.ab-cell {
  padding: .8rem .6rem .75rem;
  text-align: center;
  border-top: 2px solid transparent;
}
.ab-cell + .ab-cell { border-left: 1px solid var(--rule); }
.ab-cell.active { background: var(--amber-wash); border-top-color: var(--amber); }
.ab-slot { display: block; font-size: 1.12rem; font-weight: 600; letter-spacing: -.02em; }
.ab-dev { display: block; margin-top: .1rem; font-size: .72rem; color: var(--ink-muted); }
.ab-tag {
  display: block;
  margin-top: .4rem;
  font: 500 .6rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--ink-muted);
}
.ab-cell.active .ab-tag { color: var(--amber-text); }

/* --- Flash-image job --------------------------------------------------- */

.job-line { margin: 0; font-size: 1rem; font-weight: 500; letter-spacing: -.01em; }
.panel--done .job-line { color: var(--green); }
.panel--failed .job-line { color: var(--danger); }
.job-meta { margin: .5rem 0 0; font-size: .82rem; line-height: 1.5; color: var(--ink-muted); }
.job-meta + .job-meta { margin-top: .3rem; }
.countdown { color: var(--ink); font-weight: 500; }
.sha { font-size: .74rem; word-break: break-all; }

/* --- Confirmation dialog ----------------------------------------------- */

.modal {
  max-width: 470px;
  width: calc(100% - 2rem);
  padding: 1.45rem 1.5rem;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 26px 60px -22px rgba(20, 23, 27, .38), 0 2px 6px rgba(20, 23, 27, .06);
}
.modal::backdrop { background: rgba(20, 23, 27, .3); }
.modal h3 { margin: 0 0 .7rem; font-size: 1.15rem; font-weight: 600; letter-spacing: -.015em; }
.modal p { margin: 0; color: var(--ink-muted); font-size: .93rem; }
.modal-actions {
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  align-items: center;
  margin-top: 1.4rem;
}
.modal-actions form { margin: 0; }

/* --- Add-printer wizard ------------------------------------------------ */

.wiz-steps {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: .7rem;
  list-style: none;
  padding: 0;
  margin: 1.6rem 0 1.7rem;
  max-width: 720px;
}
.wiz-steps li {
  display: flex;
  flex-direction: column;
  gap: .55rem;
  font: 500 .66rem/1.3 var(--mono);
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--ink-muted);
}
.wiz-steps li::before { content: ""; height: 2px; background: var(--rule); border-radius: 1px; }
.wiz-steps li b { font-weight: 500; color: var(--rule-strong); margin-right: .3em; }
.wiz-steps li.done { color: var(--ink); }
.wiz-steps li.done::before { background: var(--ink); }
.wiz-steps li.done b { color: var(--ink-muted); }
.wiz-steps li.active { color: var(--ink); }
.wiz-steps li.active::before { background: var(--amber); }
.wiz-steps li.active b { color: var(--amber-text); }

.wizard { max-width: 720px; }
.wizard fieldset.wiz-step {
  display: flex;
  flex-direction: column;
  gap: 1.3rem;
  margin: 0 0 1.2rem;
  padding: 1.3rem 1.4rem 1.5rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.wizard fieldset.wiz-step legend {
  padding: 0 .5rem;
  font: 500 .68rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-muted);
}
.wizard .field { max-width: none; }
.wizard .help code, code {
  /* nowrap so a flag like --dry-run is never split across two lines, which reads as two
     different things. */
  white-space: nowrap;
  padding: .08rem .32rem;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 3px;
  font: 400 .82em/1 var(--mono);
}
.help-link { display: inline-block; margin-top: .6rem; font-size: .86rem; }
.wiz-nav { display: flex; align-items: center; gap: .5rem; }
.wiz-spacer { flex: 1; }

/* When JS is on, show only the active step. Without JS, all steps show and the single
   Save at the bottom still works. */
.wizard.js fieldset.wiz-step { display: none; }
.wizard.js fieldset.wiz-step.active { display: block; }

/* --- Auth -------------------------------------------------------------- */

.auth { max-width: 420px; margin: 3rem auto 4rem; }
.auth-card {
  padding: 2rem 1.9rem 1.8rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.auth-title { font-size: 1.5rem; margin: 0 0 .35rem; }
.auth-sub { color: var(--ink-muted); font-size: .92rem; margin: 0; }
.auth-form { display: flex; flex-direction: column; gap: 1.15rem; margin-top: 1.4rem; }
.auth .btn-google { margin-top: 1.4rem; }
.auth .divider {
  display: flex;
  align-items: center;
  gap: .85rem;
  margin: 1.2rem 0 0;
  font: 400 .7rem/1 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.auth .divider::before, .auth .divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}
.auth-note {
  margin: 1.4rem 0 0;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-muted);
  font-size: .84rem;
}
.auth-alt { margin: 1.2rem 0 0; text-align: center; color: var(--ink-muted); font-size: .9rem; }

/* --- Landing ----------------------------------------------------------- */

.hero { padding: 1rem 0 0; }
.hero-top {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: .8rem 3.5rem;
  align-items: end;
}
.hero h1 {
  margin: 0;
  font-size: clamp(2rem, 4.4vw, 2.9rem);
  line-height: 1.06;
  letter-spacing: -.032em;
  max-width: 15ch;
}
.hero .lead { margin: 0 0 .3rem; font-size: 1.05rem; color: var(--ink-muted); max-width: 46ch; }
.hero-map { margin: 3.2rem 0 0; }
.qmap-foot { margin: 1.6rem 0 0; padding-top: 1.3rem; border-top: 1px solid var(--rule); }
.qmap-foot p { margin: 0; max-width: 68ch; font-size: .86rem; color: var(--ink-muted); }
.qmap-foot code { font-size: .78rem; }
.cta-row { display: flex; flex-wrap: wrap; gap: .6rem; margin: 2.4rem 0 0; }
.hero .note { margin: .9rem 0 0; font-size: .86rem; }

/* The public page carries a heading and two buttons and nothing else, so the two-column
   hero grid has nothing to balance against and the whole thing needs centring rather than
   stretching across a width that is now mostly empty. */
.hero--plain {
  padding: 4rem 0 0;
  max-width: 34rem;
}
.hero--plain .hero-top { display: block; }
.hero--plain h1 { max-width: 20ch; }
.hero--plain .note { max-width: 44ch; color: var(--ink-muted); }

@media (max-width: 620px) {
  .hero--plain { padding-top: 2rem; }
}

/* --- Setup guide -------------------------------------------------------- */

/* The ordered path a first-time owner follows. Amber marks the one step to act on; done
   steps stay visible but recede, so the sequence reads as progress rather than a wall. */
.guide {
  margin: 1.8rem 0 0;
  padding: 1.4rem 1.6rem 1.5rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.guide > h2 {
  display: block;
  margin: 0 0 .3rem;
  font: 600 1.15rem/1.3 var(--sans);
  letter-spacing: -.015em;
  text-transform: none;
  color: var(--ink);
}
.guide > h2::after { content: none; }
.guide-lede { margin: 0 0 1.3rem; color: var(--ink-muted); font-size: .92rem; }
.guide-stale {
  margin: 0 0 1.2rem;
  padding: .7rem .9rem;
  border-left: 3px solid var(--amber);
  background: var(--amber-wash);
  font-size: .88rem;
}

.guide-steps { list-style: none; margin: 0; padding: 0; }
.guide-step {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 0 .9rem;
  padding: 0 0 .1rem;
}
/* A rail down the left, so the steps read as one run rather than seven cards. */
.guide-step:not(:last-child) .guide-num::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 30px;
  bottom: -6px;
  width: 1px;
  background: var(--rule);
}
.guide-num {
  position: relative;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  font: 500 .72rem/1 var(--mono);
  color: var(--ink-muted);
  background: var(--paper);
}
.guide-body { padding-bottom: 1.5rem; min-width: 0; }
.guide-body h3 {
  margin: .25rem 0 .3rem;
  font: 600 .98rem/1.3 var(--sans);
  letter-spacing: -.01em;
  color: var(--ink);
}
.guide-body p { margin: 0 0 .5rem; font-size: .89rem; color: var(--ink-muted); max-width: 68ch; }
.guide-body .keybox { font-size: .78rem; white-space: pre-wrap; word-break: break-all; margin: .1rem 0 .6rem; }
.guide-note { color: var(--amber-text); }

.guide-step.is-done .guide-num {
  background: var(--green);
  border-color: var(--green);
  color: #fff;
}
.guide-step.is-done .guide-body h3 { color: var(--ink-muted); font-weight: 500; }
.guide-step.is-done .guide-body > p { font-size: .84rem; opacity: .72; }

.guide-step.is-current .guide-num {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--ink);
}
.guide-step.is-current .guide-body h3 { color: var(--ink); }

/* Steps ahead of the current one recede but stay readable. They used to be titles only,
   which meant the two steps after the flash were blank headings at the moment an owner most
   needed to know what was coming and what to have ready. */
.guide-step.is-ahead .guide-body h3 { color: var(--ink-muted); }
.guide-step.is-ahead .guide-body { opacity: .66; }

/* What a command or the portal actually does, folded away except on the step in hand. */
.guide-detail { margin: 0 0 .7rem; }
.guide-detail > summary {
  cursor: pointer;
  font: 500 .82rem/1.3 var(--sans);
  color: var(--ink-muted);
  letter-spacing: .01em;
}
.guide-detail > summary:hover { color: var(--ink); }
.guide-detail-list {
  margin: .5rem 0 0;
  padding: 0 0 0 1.2rem;
  max-width: 68ch;
  font-size: .85rem;
  color: var(--ink-muted);
}
.guide-detail-list li { margin: 0 0 .3rem; }

/* Why the portal is waiting. On a step it can see for itself this explains the absence of a
   button, which is otherwise indistinguishable from a missing one. */
.guide-waiting {
  margin: .6rem 0 .7rem !important;
  padding: .55rem .8rem;
  border-left: 2px solid var(--rule-strong);
  background: var(--bg);
  font-size: .85rem !important;
}

.guide-optout { margin: .7rem 0 .5rem; }
.guide-optout .checkbox { font-size: .87rem; }
.guide-optout .help { display: block; margin: .3rem 0 0 1.6rem; max-width: 62ch; }

.guide-badge {
  margin-left: .5rem;
  padding: .1rem .4rem;
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  font: 500 .68rem/1.5 var(--sans);
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  vertical-align: middle;
}
.guide-undo { margin: .2rem 0 0; }
.linkish {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: .82rem;
  color: var(--ink-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.linkish:hover { color: var(--ink); }

/* Finished setup collapses to one line, but stays on the page: the commands and the
   explanations are worth reaching again after a firmware update or a second printer. */
.guide.is-complete { padding-top: 1.1rem; padding-bottom: 1.1rem; }
.guide-done-wrap > summary { cursor: pointer; list-style-position: outside; }
.guide-done-wrap > summary h2 {
  display: inline;
  margin: 0;
  font: 600 1.05rem/1.3 var(--sans);
  color: var(--ink);
}
.guide-done-wrap > summary h2::after { content: none; }
.guide-done-wrap > summary .guide-lede { display: block; margin: .3rem 0 0; }
.guide-done-wrap[open] > summary { margin-bottom: 1.2rem; }

/* A state that is legal but probably not what the owner meant, and costs a reflash to undo. */
.warnbox {
  margin: .6rem 0 .8rem;
  padding: .7rem .9rem;
  border-left: 3px solid var(--amber);
  background: var(--amber-wash);
  font-size: .88rem;
  max-width: 68ch;
}

/* A control that should not be reached for by accident. */
.danger-disclosure { margin: .6rem 0 0; }
.danger-disclosure > summary {
  cursor: pointer;
  font-size: .86rem;
  color: var(--ink-muted);
}
.danger-disclosure > summary:hover { color: var(--ink); }
.danger-disclosure > p { margin: .6rem 0 .7rem; max-width: 68ch; }

@media (max-width: 620px) {
  .guide { padding: 1.1rem 1.1rem 1.2rem; }
  .guide-step { grid-template-columns: 24px minmax(0, 1fr); gap: 0 .7rem; }
}

/* --- Attestation log --------------------------------------------------- */

.table-scroll { overflow-x: auto; }
.attest-table { width: 100%; border-collapse: collapse; margin-top: .2rem; font-size: .86rem; }
.attest-table th {
  padding: .5rem 1.2rem .5rem 0;
  text-align: left;
  border-bottom: 1px solid var(--rule);
  font: 500 .64rem/1.5 var(--mono);
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-muted);
  white-space: nowrap;
}
.attest-table td {
  padding: .6rem 1.2rem .6rem 0;
  border-bottom: 1px solid var(--rule);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Responsive -------------------------------------------------------- */

@media (max-width: 900px) {
  .sheet { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  /* Stacked, the actions belong under the title, not below the attestation log. */
  .sheet-rail {
    position: static;
    order: -1;
    align-items: start;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  }
  .hero-top { grid-template-columns: minmax(0, 1fr); gap: 1.15rem; align-items: start; }
  .hero .lead { max-width: 58ch; }
}

@media (max-width: 620px) {
  .content { padding: 0 1.1rem; margin: 2rem auto 3rem; }
  .site-header, .site-footer { padding-left: 1.1rem; padding-right: 1.1rem; }
  .site-header nav { gap: 1.05rem; }
  .detail { grid-template-columns: minmax(0, 1fr); }
  .detail dt { padding: .8rem 0 .1rem; border-bottom: 0; }
  .detail dd { padding: 0 0 .8rem; }
  .wiz-steps { grid-auto-flow: row; gap: .45rem; }
  .wiz-steps li { flex-direction: row; align-items: center; gap: .6rem; }
  .wiz-steps li::before { width: 18px; height: 2px; flex: none; }
  .cta-row .btn, .actions .btn { flex: 1 1 auto; }
  .hero h1, .hero .lead { max-width: none; }

  /* Leader lines need horizontal room; below this width the marks stack. */
  .qmap-body { padding-bottom: 0; }
  .qmap-marks { display: grid; gap: .9rem; margin-top: 1.2rem; }
  .qmap-mark {
    position: static;
    max-width: none;
    padding-left: .7rem;
    border-left: 2px solid var(--rule-strong);
  }
  .qmap-mark::before { display: none; }
  .qmap--writing .qmap-mark--key,
  .qmap--done .qmap-mark--key { border-left-color: var(--amber); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; }
  .qmap--writing .qmap-strip::after {
    width: 100%;
    background: var(--amber-wash);
    animation: none;
  }
}

@media (forced-colors: active) {
  .qmap-strip, .card, .panel, .job { border: 1px solid CanvasText; }
  .status::before, .qmap-tick { forced-color-adjust: none; }
}
