/* Melagen Design Platform — app.css
   Phase 1: project dashboard + create form + project detail.
   Reuses the /quick visual language (dark ink header, red accent, white
   cards) — see radengine/static/quick.html's <style> block for the source
   of truth on tokens/card/button feel. No framework, no build step. */

:root {
  --red:#d93025;
  --ink:#16181c;
  --line:#e3e5e8;
  --muted:#6a7078;
  --ok:#1a7f37;
  --bg:#fafafa;
  --card:#fff;
}

* { box-sizing:border-box; }

body {
  margin:0;
  font:15px/1.55 system-ui,"Segoe UI",Roboto,sans-serif;
  color:var(--ink);
  background:var(--bg);
}

/* ---------- header (shell markup, styled here) ---------- */

.appheader {
  background:var(--ink);
  color:#fff;
  padding:1rem 1.5rem;
  display:flex;
  align-items:baseline;
  gap:.6rem;
  flex-wrap:wrap;
}
.wordmark {
  font-weight:800;
  letter-spacing:.04em;
  font-size:1.15rem;
  color:#fff;
  text-decoration:none;
}
.wordmark:hover { text-decoration:none; }
.wordmark .labs { color:var(--red); }
.wordmark .star,
.star { color:var(--red); }
.apptag { color:#c8ccd2; font-size:.85rem; }
.appbeta {
  font-size:.72rem;
  border:1px solid #555;
  border-radius:99px;
  padding:.15rem .6rem;
  color:#c8ccd2;
}
.appquick {
  margin-left:auto;
  color:#c8ccd2;
  font-size:.85rem;
  text-decoration:none;
}
.appquick:hover { color:#fff; text-decoration:underline; }

/* ---------- layout ---------- */

.wrap {
  max-width:880px;
  margin:0 auto;
  padding:1.5rem;
}

/* Wide pages: 880px is right for the forms (measure/readability), but it
   strangled the two pages that show SPATIAL content — the shielding page's 3D
   viewer was squeezed to ~420px with dead space beside it, and the three option
   cards had no room to sit side by side. app.js adds .wide on those routes only. */
.wrap.wide { max-width:1240px; }

.crumbs {
  font-size:.82rem;
  color:var(--muted);
  margin-bottom:1rem;
  display:flex;
  align-items:center;
  gap:.4rem;
  flex-wrap:wrap;
}
.crumbs a {
  color:var(--muted);
  text-decoration:none;
}
.crumbs a:hover { color:var(--red); text-decoration:underline; }

.rowbetween {
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:.75rem;
}

.muted { color:var(--muted); }

[hidden] { display:none !important; }

/* ---------- buttons ---------- */

.btn {
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:.4rem;
  padding:.6rem 1rem;
  border-radius:10px;
  font:inherit;
  font-weight:650;
  cursor:pointer;
  border:1px solid var(--line);
  background:#fff;
  color:var(--ink);
  text-decoration:none;
  line-height:1.2;
  transition:background .15s, border-color .15s, color .15s;
}
a.btn { text-decoration:none; }
.btn:hover { border-color:#c7cad0; }

.btn.primary {
  background:var(--ink);
  color:#fff;
  border:0;
}
.btn.primary:hover { background:#232630; }

.btn.ghost {
  background:transparent;
  border-color:var(--line);
}
.btn.ghost:hover { background:#f2f3f4; }

.btn.danger {
  color:var(--red);
  border-color:#f0c9c4;
  background:#fff;
}
.btn.danger:hover { background:rgba(217,48,37,.06); }

.btn.sm {
  padding:.35rem .7rem;
  font-size:.85rem;
  border-radius:8px;
}

.btn:disabled,
.btn[disabled] {
  opacity:.5;
  cursor:not-allowed;
}

.btn:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

@media (prefers-reduced-motion: reduce) {
  .btn { transition:none; }
}

/* ---------- card ---------- */

.card {
  background:var(--card);
  border:1px solid var(--line);
  border-radius:12px;
  padding:1.2rem 1.4rem;
}

/* ---------- page head ---------- */

.pagehead {
  display:block;
  margin-bottom:1rem;
}
.pagehead h1 {
  font-size:1.5rem;
  font-weight:750;
  margin:0 0 .25rem;
}
.pagehead .sub {
  color:var(--muted);
  margin:0;
}

/* ---------- dashboard ---------- */

.dash-head {
  display:flex;
  justify-content:space-between;
  align-items:center;
  margin-bottom:1rem;
  gap:.75rem;
  flex-wrap:wrap;
}
.dash-title {
  font-size:1.5rem;
  font-weight:750;
  margin:0;
}

.projgrid {
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  gap:1rem;
}

.projcard {
  background:var(--card);
  border:1px solid var(--line);
  border-radius:12px;
  padding:1.2rem 1.4rem;
  display:flex;
  flex-direction:column;
  transition:box-shadow .15s, border-color .15s, transform .15s;
}
.projcard:hover {
  border-color:#c7cad0;
  box-shadow:0 4px 16px rgba(22,24,28,.06);
  transform:translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
  .projcard { transition:none; }
  .projcard:hover { transform:none; }
}

.projcard-top {
  display:flex;
  flex-direction:column;
  gap:.2rem;
  margin-bottom:.2rem;
}

.projname {
  font-weight:750;
  font-size:1.05rem;
  color:var(--ink);
}

.projmeta {
  color:var(--muted);
  font-size:.82rem;
}

.projcard-actions {
  display:flex;
  gap:.5rem;
  margin-top:.9rem;
}

.empty {
  text-align:center;
  color:var(--muted);
  border:1.5px dashed var(--line);
  border-radius:12px;
  padding:2.5rem 1.5rem;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.7rem;
}
.empty p {
  margin:0;
  max-width:28rem;
}

/* ---------- checklist ---------- */

.checklist {
  margin:.6rem 0;
  display:flex;
  flex-direction:column;
  gap:.3rem;
}

.chk {
  display:flex;
  align-items:center;
  gap:.5rem;
  font-size:.82rem;
  color:var(--ink);
}

.chk-ic {
  flex:none;
  width:1.1rem;
  height:1.1rem;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  color:var(--muted);
  font-size:.85rem;
  line-height:1;
}
.chk-ic::before { content:"\25CB"; } /* ○ */

.chk.done .chk-ic { color:var(--ok); }
.chk.done .chk-ic::before { content:"\2713"; } /* ✓ */

.chk-label {
  flex:1;
  min-width:0;
}
.chk.done .chk-label { color:var(--ink); font-weight:600; }

.chk-state {
  flex:none;
  font-size:.7rem;
  text-transform:uppercase;
  letter-spacing:.03em;
  color:var(--muted);
}
.chk.done .chk-state { color:var(--ok); font-weight:650; }

/* ---------- form (create / detail) ---------- */

.form {
  display:grid;
  gap:.9rem;
  max-width:34rem;
}

.field {
  display:flex;
  flex-direction:column;
  gap:.3rem;
}

.field-label {
  font-weight:650;
  font-size:.85rem;
}

.field input,
.field textarea {
  width:100%;
  padding:.5rem .65rem;
  border:1px solid var(--line);
  border-radius:8px;
  font:inherit;
  color:var(--ink);
  background:#fff;
}

.field textarea {
  resize:vertical;
  min-height:3.4rem;
}

.field input:focus,
.field textarea:focus {
  outline:none;
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.field input::placeholder,
.field textarea::placeholder {
  color:#9aa0a8;
}

.field-hint {
  color:var(--muted);
  font-size:.78rem;
}

.form-actions {
  display:flex;
  gap:.7rem;
  margin-top:.3rem;
}

.err {
  color:var(--red);
  font-size:.88rem;
  /* L1: multi-line server errors (the old-server-build echo warnings; "server
     couldn't analyze this file:\n<detail>") must not collapse to one line. */
  white-space:pre-wrap;
}

/* ---------- project detail ---------- */

.detail-head {
  margin-bottom:.2rem;
}

.detail-sub {
  color:var(--muted);
}

/* ---------- responsive ---------- */

@media (max-width:640px) {
  .wrap { padding:1rem; }
  .dash-head { flex-direction:column; align-items:flex-start; }
  .rowbetween { flex-direction:column; align-items:flex-start; }
  .projcard-actions { flex-wrap:wrap; }
}

/* ---------- focus visibility (keyboard nav) ---------- */

a:focus-visible,
input:focus-visible,
textarea:focus-visible,
button:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

/* =====================================================================
   Phase 2 — mission wizard (Orbit / Mission timing / Radiation
   requirements / Summary + BOM gate). Mirrors quick.html's orbit-card
   and modal look (see quick.html <style> — .orbit/.orbit.sel/.orbit.off,
   .modal-backdrop/.modal/.modal-title/.modal-body/.modal-actions) so
   Phase 2 reads as the same product as Phase 1 and /quick.
   ===================================================================== */

/* ---------- section scaffolding ---------- */

.section {
  margin-top:1.6rem;
}
.section:first-child { margin-top:0; }

.sectitle {
  font-size:.8rem;
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--muted);
  font-weight:700;
  margin:0 0 .7rem;
  display:flex;
  align-items:center;
}

.sectitle .num {
  display:inline-grid;
  place-items:center;
  width:1.35rem;
  height:1.35rem;
  border-radius:50%;
  background:var(--ink);
  color:#fff;
  font-size:.75rem;
  margin-right:.45rem;
  flex:none;
}

/* ---------- orbit cards (mirrors quick.html .orbit) ---------- */

.orbits {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:.6rem;
}

.orbit {
  border:1.5px solid var(--line);
  border-radius:10px;
  padding:.6rem .7rem;
  cursor:pointer;
  position:relative;
  background:#fff;
  transition:border-color .15s, box-shadow .15s;
}
.orbit strong { display:block; font-size:.92rem; }
.orbit small { color:var(--muted); }

.orbit.sel {
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.orbit.off {
  opacity:.55;
  cursor:not-allowed;
}
.orbit.off:hover,
.orbit.off:focus-visible {
  border-color:var(--line);
  box-shadow:none;
}

.orbit .soon {
  position:absolute;
  top:.4rem;
  right:.5rem;
  font-size:.6rem;
  background:#eee;
  border-radius:99px;
  padding:.1rem .45rem;
  color:var(--muted);
}

.orbit:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

@media (prefers-reduced-motion: reduce) {
  .orbit { transition:none; }
}

/* ---------- custom-orbit disabled block ---------- */

.customorbit {
  border:1px dashed var(--line);
  border-radius:10px;
  padding:.8rem .9rem;
  background:#f8f9fa;
  opacity:.7;
}

.customgrid {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(9rem,1fr));
  gap:.6rem;
}

.customorbit input:disabled {
  background:#f1f2f4;
  color:var(--muted);
  cursor:not-allowed;
}

/* ---------- radio / choice rows ---------- */

.radios {
  display:flex;
  gap:.8rem;
  flex-wrap:wrap;
  margin-top:.3rem;
}

.radio {
  display:inline-flex;
  align-items:center;
  gap:.4rem;
  padding:.45rem .8rem;
  border:1.5px solid var(--line);
  border-radius:9px;
  cursor:pointer;
  background:#fff;
  font-weight:600;
  font-size:.9rem;
  transition:border-color .15s, box-shadow .15s;
}

.radio.sel {
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.radio input {
  accent-color:var(--red);
  margin:0;
  cursor:pointer;
}

.radio:focus-within {
  outline:2px solid var(--red);
  outline-offset:2px;
}

@media (prefers-reduced-motion: reduce) {
  .radio { transition:none; }
}

.inline {
  display:flex;
  gap:.8rem;
  flex-wrap:wrap;
  align-items:flex-end;
}

select.sel2 {
  padding:.5rem .65rem;
  border:1px solid var(--line);
  border-radius:8px;
  font:inherit;
  background:#fff;
  cursor:pointer;
  color:var(--ink);
}
select.sel2:focus {
  outline:none;
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}
select.sel2:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

/* ---------- callout notes ---------- */

.bompointer {
  border:1px solid #cdd7ea;
  background:#f3f6fc;
  border-radius:8px;
  padding:.55rem .75rem;
  font-size:.85rem;
  color:#33415c;
  margin-top:.5rem;
}

/* ---------- summary + missing-fields panels ---------- */

.summary-row {
  display:flex;
  justify-content:space-between;
  gap:1rem;
  padding:.35rem 0;
  border-bottom:1px solid var(--line);
}
.summary-row:last-child { border-bottom:0; }

.summary-k {
  color:var(--muted);
  font-size:.85rem;
  font-weight:600;
}

.summary-v {
  font-weight:650;
  font-variant-numeric:tabular-nums;
  text-align:right;
}

.summary-v.pending {
  color:var(--muted);
  font-weight:500;
  font-style:italic;
}

.missing {
  border:1px solid #e2c06b;
  background:#fdf6e3;
  border-radius:8px;
  padding:.6rem .8rem;
  color:#5c4a12;
  font-size:.88rem;
  margin-top:.8rem;
}
.missing ul {
  margin:.3rem 0 0;
  padding-left:1.1rem;
}
.missing li { margin:.1rem 0; }

.missing.ok {
  border-color:#b7d9c1;
  background:#eef7f1;
  color:#1a5c31;
}

/* ---------- BOM gate ---------- */

.gate {
  margin-top:1.4rem;
  padding-top:1.1rem;
  border-top:1px solid var(--line);
  display:flex;
  gap:.8rem;
  flex-wrap:wrap;
}

.gate .btn {
  flex:1;
  min-width:15rem;
  text-align:center;
  justify-content:center;
}

/* ---------- skip-warning modal (mirrors quick.html) ---------- */

.modal-backdrop {
  position:fixed;
  inset:0;
  background:rgba(22,24,28,.55);
  display:flex;
  align-items:center;
  justify-content:center;
  z-index:50;
  padding:1rem;
}
.modal-backdrop[hidden] { display:none; }

.modal {
  background:#fff;
  border-radius:14px;
  max-width:34rem;
  width:100%;
  padding:1.3rem 1.4rem;
  box-shadow:0 12px 40px rgba(0,0,0,.28);
}

.modal-title {
  font-weight:800;
  font-size:1.05rem;
  color:var(--red);
  margin-bottom:.5rem;
}

.modal-body {
  font-size:.92rem;
  line-height:1.55;
}
.modal-body p { margin:.5rem 0; }

.warnlist {
  margin:.4rem 0 .2rem;
  padding-left:1.2rem;
}
.warnlist li { margin:.22rem 0; }

.modal-actions {
  display:flex;
  justify-content:flex-end;
  gap:.6rem;
  margin-top:1.1rem;
  flex-wrap:wrap;
}

/* ---------- step-placeholder page ---------- */

.placeholder {
  border:1px dashed var(--line);
  border-radius:12px;
  padding:2rem 1.4rem;
  text-align:center;
  color:var(--muted);
  background:#fbfbfc;
}
.placeholder h2 {
  color:var(--ink);
  margin:.2rem 0 .5rem;
  font-size:1.1rem;
}

/* ---------- sticky action bar ---------- */

.stepactions {
  display:flex;
  gap:.7rem;
  flex-wrap:wrap;
  margin-top:1.4rem;
  padding-top:1rem;
  border-top:1px solid var(--line);
}

/* ---------- Phase 2 responsive ---------- */

@media (max-width:640px) {
  .gate { flex-direction:column; }
  .gate .btn { min-width:0; width:100%; }
  .customgrid { grid-template-columns:1fr; }
}

/* =====================================================================
   Phase 3 — watermarked BOM dummy page (recommended-TID editable field,
   sample component table, disabled search/filters). Everything on this
   page must read unmistakably as a placeholder, not a real result.
   ===================================================================== */

/* ---------- .btn.wide (not previously defined) ---------- */

.btn.wide {
  width:100%;
  justify-content:center;
  text-align:center;
}

/* ---------- placeholder watermark banner ---------- */

.bombanner {
  position:relative;
  overflow:hidden;
  background:#fff4e0;
  border:1px solid #e2c06b;
  border-left:5px solid var(--red);
  border-radius:10px;
  padding:.8rem 1rem;
  margin-bottom:1.3rem;
  color:#5c4a12;
  font-weight:650;
}
.bombanner::before {
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
  background:repeating-linear-gradient(
    45deg,
    rgba(217,48,37,.05),
    rgba(217,48,37,.05) 10px,
    transparent 10px,
    transparent 20px
  );
}
.bombanner > * {
  position:relative;
}
.bombanner strong { color:var(--red); }

.bombanner-sub {
  font-weight:400;
  font-size:.85rem;
  margin-top:.25rem;
}

/* ---------- recommended-TID editable field block ---------- */

.bomreco {
  border:1.5px solid #cdd7ea;
  background:linear-gradient(180deg,#f6f8fc,#fff);
  border-radius:12px;
  padding:1.1rem 1.3rem;
  margin-bottom:1.1rem;
}

.bomreco-label {
  font-size:.7rem;
  letter-spacing:.05em;
  font-weight:700;
  color:var(--muted);
  text-transform:uppercase;
}

.bomreco-row {
  display:flex;
  align-items:baseline;
  gap:.6rem;
  margin-top:.35rem;
}

input.bomreco-input {
  font-size:1.6rem;
  font-weight:750;
  width:6.5rem;
  padding:.3rem .5rem;
  border:1.5px solid var(--line);
  border-radius:8px;
  font-variant-numeric:tabular-nums;
  font-family:inherit;
  color:var(--ink);
  background:#fff;
}
input.bomreco-input:focus {
  outline:none;
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.bomreco-unit {
  font-size:1.1rem;
  font-weight:650;
  color:var(--muted);
}

.bomreco-explain {
  margin-top:.6rem;
}
.bomreco-explain p {
  margin:.25rem 0;
  font-size:.85rem;
  color:var(--muted);
  line-height:1.5;
}

/* ---------- sample component table ---------- */

.bomtable-wrap {
  overflow-x:auto;
}

table.bomtable {
  width:100%;
  border-collapse:collapse;
  font-size:.85rem;
  font-variant-numeric:tabular-nums;
}

.bomtable thead th {
  text-align:left;
  padding:.4rem .6rem;
  border-bottom:1.5px solid var(--line);
  color:var(--muted);
  font-weight:650;
  font-size:.7rem;
  text-transform:uppercase;
  letter-spacing:.04em;
  white-space:nowrap;
}

.bomtable tbody td {
  padding:.45rem .6rem;
  border-bottom:1px solid var(--line);
  vertical-align:middle;
}

.bomtable tbody tr:last-child td {
  border-bottom:0;
}

td.num, th.num {
  text-align:right;
}

.bomstatus {
  display:inline-block;
  font-size:.68rem;
  font-weight:700;
  padding:.12rem .5rem;
  border-radius:99px;
  text-transform:uppercase;
  letter-spacing:.03em;
}

.bomstatus.ok {
  background:#e6f3ea;
  color:var(--ok);
}

.bomstatus.warn {
  background:#fdf6e3;
  color:#8a6d1a;
}

.bomstatus.bad {
  background:#fdecea;
  color:var(--red);
}

/* ---------- disabled search / filters bar ---------- */

.bomfilters {
  display:flex;
  gap:.6rem;
  align-items:center;
  flex-wrap:wrap;
  margin:.9rem 0 .5rem;
  opacity:.6;
}

input.bomsearch {
  flex:1;
  min-width:12rem;
  padding:.45rem .6rem;
  border:1px solid var(--line);
  border-radius:8px;
  background:#f1f2f4;
  color:var(--muted);
  cursor:not-allowed;
  font:inherit;
}

select.bomfilter {
  padding:.45rem .6rem;
  border:1px solid var(--line);
  border-radius:8px;
  background:#f1f2f4;
  color:var(--muted);
  cursor:not-allowed;
  font:inherit;
}

.bomfilters .soonpill {
  font-size:.6rem;
  background:#eee;
  color:var(--muted);
  border-radius:99px;
  padding:.1rem .45rem;
}

/* ---------- Phase 3 responsive ---------- */

@media (max-width:640px) {
  .bomfilters { flex-wrap:wrap; }
  .bomreco-row { flex-wrap:wrap; }
}

/* =====================================================================
   Phase 4 — Shielding page (two-column layout: controls/results left,
   3D viewer right; mission summary chip; structured shield control;
   run + result cards; TID-vs-target verdict banner; 0-ray override
   disclosure).

   The viewer / parts-inspector / shield-chip / AI-progress-overlay rules
   below are PORTED VERBATIM from quick.html's <style> block (same
   --red/--ink/--line/--muted/--ok tokens) so this page's 3D viewer is
   pixel-identical to /quick. Do not restyle them here — if the viewer
   needs to change, it changes in quick.html first and gets re-ported.
   ===================================================================== */

/* ---------- ported verbatim from quick.html: 3D viewer ---------- */

.viewerpanel { display:flex; flex-direction:column; min-width:0; }
.viewer { position:relative; flex:1; min-height:540px; height:clamp(540px, calc(100vh - 260px), 860px);
          border:1px solid var(--line); border-radius:10px; overflow:hidden; background:#f4f5f7; }
.viewer canvas { display:block; }
.voverlay { position:absolute; inset:0; display:grid; place-content:center; text-align:center;
            gap:.35rem; pointer-events:none; z-index:2; }
.voverlay[hidden] { display:none; }  /* author display:grid would otherwise beat the hidden attr */
.voverlay .vtitle { color:var(--muted); font-weight:650; }
.voverlay .vhint { color:#9aa0a8; font-size:.8rem; }
/* empty state doubles as an upload button (only visible when no model is
   loaded, so it never steals clicks from the 3D orbit controls) */
#viewerEmpty { pointer-events:auto; cursor:pointer; transition:background .15s; }
#viewerEmpty:hover, #viewerEmpty.hover { background:rgba(217,48,37,.045); }
/* not present in quick.html (no dedicated rule there) — added here to match
   this app's global focus-visible convention (see bottom of Phase 1). */
#viewerEmpty:focus-visible { outline:2px solid var(--red); outline-offset:2px; }
.spinner { width:34px; height:34px; margin:0 auto .7rem; border-radius:50%;
           border:3px solid #d7dade; border-top-color:var(--red);
           animation:spin .8s linear infinite; }
@keyframes spin { to { transform:rotate(360deg); } }
.vchip { position:absolute; top:.7rem; left:.7rem; z-index:3; background:#fff; border:1px solid var(--line);
         border-radius:99px; padding:.2rem .7rem; font-size:.75rem; color:var(--muted); }

/* ---------- ported verbatim from quick.html: parts inspector ---------- */

.vtoggle { position:absolute; top:.7rem; z-index:3; display:flex; align-items:center; gap:.4rem;
           background:#fff; border:1px solid var(--line); border-radius:99px;
           padding:.22rem .7rem; font:inherit; font-size:.75rem; color:var(--ink);
           cursor:pointer; user-select:none; }
.vtoggle input { margin:0; accent-color:var(--red); cursor:pointer; }
#vPartsChip { left:.7rem; font-weight:650; }
#vIntsChip { right:.7rem; }
/* shield visibility chip sits at the corner too; JS slides it left of the
   internals chip whenever that one exists (shieldChipPos). */
#vShieldChip { right:.7rem; }
.vparts { position:absolute; top:2.7rem; left:.7rem; z-index:4; width:16rem; max-width:70%;
          max-height:50%; display:flex; flex-direction:column; overflow:hidden;
          background:rgba(255,255,255,.96); border:1px solid var(--line); border-radius:10px;
          font-size:.78rem; }
.vparts[hidden] { display:none; }   /* author display:flex would otherwise beat the hidden attr */
.vparts-list { overflow-y:auto; padding:.25rem .55rem; scrollbar-width:thin; }
.vparts-list::-webkit-scrollbar { width:6px; }
.vparts-list::-webkit-scrollbar-thumb { background:#d0d3d8; border-radius:99px; }
.vpart { display:flex; align-items:center; gap:.45rem; padding:.16rem 0; cursor:pointer; }
.vpart input { margin:0; accent-color:var(--red); cursor:pointer; }
.vpart.unmatched { opacity:.45; cursor:default; }
.vpart-name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:600; }
.vbadge { flex:none; font-size:.58rem; font-weight:700; letter-spacing:.04em; border-radius:99px;
          padding:.05rem .4rem; border:0; font-family:inherit; line-height:inherit; }
.vbadge.enc { background:rgba(217,48,37,.08); color:var(--red); }
.vbadge.int { background:#eef0f2; color:var(--muted); }
/* badge as a <button> = engineer class override (click ENC <-> int); an active
   override renders as the FILLED variant so it reads as "hand-set". */
button.vbadge { cursor:pointer; }
.vbadge.ovr.enc { background:var(--red); color:#fff; }
.vbadge.ovr.int { background:var(--muted); color:#fff; }
.vpart-vol { flex:none; color:var(--muted); font-variant-numeric:tabular-nums; }
.vparts-stale { border-top:1px solid var(--line); padding:.3rem .55rem; font-size:.68rem;
                font-weight:600; color:#b26a00; }
.vparts-hint { border-top:1px solid var(--line); padding:.35rem .55rem; color:#9aa0a8; font-size:.68rem; }

/* ---------- ported verbatim from quick.html: AI-progress overlay ---------- */

.aiprog { position:absolute; left:.7rem; right:.7rem; bottom:.7rem; z-index:4;
          background:rgba(22,24,28,.93); color:#e8eaed; border-radius:10px;
          padding:.6rem .8rem; box-shadow:0 4px 20px rgba(0,0,0,.25); }
.aiprog[hidden] { display:none; }
.aiprog-head { display:flex; justify-content:space-between; font-size:.8rem;
               font-weight:650; margin-bottom:.4rem; }
.aiprog-bar { height:6px; background:#3a3f47; border-radius:99px; overflow:hidden; }
.aiprog-fill { height:100%; width:0; background:var(--red); transition:width .3s ease; }
.aiprog-log { margin-top:.5rem; max-height:120px; overflow-y:auto; white-space:pre-wrap;
              font-family:ui-monospace,Menlo,Consolas,monospace; font-size:.72rem;
              line-height:1.5; color:#c8ccd2; }
.aiprog-log .ok { color:#7ee2a8; }
.aiprog-log .err { color:#ff8a80; }
.aiprog-log .dim { color:#8a9099; }
.aiprog-log .warn { color:#ffcf6b; }
.aiprog-fail { color:#ff8a80; font-weight:700; margin:.1rem 0 .3rem; }
.aiprog-dismiss { border:1px solid #555; background:transparent; color:#e8eaed;
                  border-radius:6px; font:inherit; font-size:.72rem; line-height:1;
                  padding:.2rem .5rem; cursor:pointer; }
.aiprog-dismiss[hidden] { display:none; }

/* ---------- ported verbatim from quick.html: upload progress bar ---------- */

.upbar { height:5px; background:#eceef0; border-radius:99px; overflow:hidden; margin-top:.5rem; }
.upbar-fill { height:100%; width:0%; background:var(--red); transition:width .25s ease; }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation:none; }
  .aiprog-fill, .upbar-fill, #viewerEmpty { transition:none; }
}

/* ---------- Phase 4: two-column shielding layout ---------- */

.shldgrid {
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  gap:1.4rem;
  align-items:start;
}
@media (max-width:900px) {
  .shldgrid { grid-template-columns:1fr; }
}

.shld-left, .shld-right {
  min-width:0;
}
.shld-right .viewerpanel {
  height:100%;
}

/* ---------- mission summary chip (auto-filled, links to Mission step) ---------- */

.missionchip {
  border:1px solid var(--line);
  border-radius:10px;
  padding:.55rem .8rem;
  background:#f4f6f7;
  font-size:.85rem;
  display:flex;
  gap:.6rem;
  align-items:center;
  flex-wrap:wrap;
  margin-bottom:1rem;
}
.missionchip a {
  margin-left:auto;
  color:var(--red);
  font-weight:650;
  white-space:nowrap;
  text-decoration:none;
}
.missionchip a:hover { text-decoration:underline; }
.missionchip .mc-k { color:var(--muted); }
.missionchip .mc-v { font-weight:650; }

/* ---------- structured shield control ("satellite wall") ---------- */

.wallrow {
  display:flex;
  gap:.8rem;
  align-items:flex-end;
  flex-wrap:wrap;
}

.wallnote {
  color:var(--muted);
  font-size:.78rem;
}

/* ---------- run button + results ---------- */

.runrow {
  margin:1rem 0;
}
.runrow .btn.wide {
  display:flex;
}

.rescards {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
  gap:.7rem;
  margin:.8rem 0;
}

.rescard {
  border:1px solid var(--line);
  border-radius:10px;
  padding:.7rem .9rem;
  background:#fff;
}
.rescard .v {
  font-size:1.35rem;
  font-weight:750;
  font-variant-numeric:tabular-nums;
}
.rescard .k {
  font-size:.68rem;
  text-transform:uppercase;
  letter-spacing:.06em;
  color:var(--muted);
}

.resline {
  font-size:.82rem;
  color:var(--muted);
  margin:.2rem 0;
  line-height:1.5;
}

/* ---------- the verdict banner (TID vs carried effective target) ---------- */

.verdict {
  border-radius:10px;
  padding:.8rem 1rem;
  font-weight:700;
  margin:.9rem 0;
  display:flex;
  gap:.6rem;
  align-items:baseline;
  flex-wrap:wrap;
}
.verdict.ok { background:#e8f4ec; color:var(--ok); }
.verdict.bad { background:#fdeceb; color:var(--red); }
.verdict .ratio {
  display:inline-block;
  border-radius:99px;
  padding:.14rem .55rem;
  font-size:.8rem;
  font-weight:700;
}
.verdict.ok .ratio { background:#d7ebdd; }
.verdict.bad .ratio { background:#f8d5d2; }

/* ---------- 0-ray override disclosure (heuristic) ---------- */

.zeroray {
  border:1px solid #e2c06b;
  background:#fdf6e3;
  color:#5c4a12;
  border-radius:8px;
  padding:.5rem .7rem;
  font-size:.8rem;
  margin-top:.5rem;
}

/* ---------- Phase 4 responsive ---------- */

@media (max-width:640px) {
  .missionchip { flex-direction:column; align-items:flex-start; }
  .missionchip a { margin-left:0; }
  .wallrow { flex-direction:column; align-items:stretch; }
  .verdict { flex-direction:column; align-items:flex-start; }
}

/* =====================================================================
   Persistent left step rail (project pages only) — a nav spine mapping
   Mission Parameters / BOM analysis / Radiation Analysis / Options & submit
   so the engineer can move back and forth freely. Hidden on the dashboard
   and create-form pages (app.js's hideRail()), in which case .shell must
   collapse to look EXACTLY like the old bare <main class="wrap"> — hence
   flex (not grid): with .rail [hidden] removed from flow, .wrap simply
   takes the full row again.
   ===================================================================== */

.shell {
  display:flex;
  align-items:flex-start;
}

.rail {
  flex:0 0 208px;
  /* A flex item's default min-width:auto is its CONTENT's min size, which
     overrides the 208px basis — a long unbreakable project name then widened
     the rail and ate the content column (the .rail-proj ellipsis never
     engaged, because its parent was never actually constrained). */
  min-width:0;
  max-width:208px;
  position:sticky;
  top:1.5rem;
  align-self:start;
  padding:1.4rem .8rem 1.4rem 1.2rem;
  border-right:1px solid var(--line);
}
.rail[hidden] { display:none; }

.shell > .wrap {
  flex:1;
  min-width:0;
}

.rail-proj {
  display:block;
  font-weight:750;
  font-size:.9rem;
  color:var(--ink);
  text-decoration:none;
  margin-bottom:.9rem;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.rail-proj:hover { color:var(--red); }

.railsteps {
  display:flex;
  flex-direction:column;
  gap:.1rem;
}

.railstep {
  display:flex;
  align-items:center;
  gap:.55rem;
  padding:.5rem .6rem;
  border-radius:8px;
  font-size:.87rem;
  color:var(--muted);
  text-decoration:none;
  cursor:pointer;
  transition:background .15s, color .15s;
}
.railstep:hover { background:#f1f2f4; color:var(--ink); }

.railstep-ic {
  flex:none;
  width:1.05rem;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  font-size:.85rem;
  line-height:1;
}
.railstep-ic::before { content:"\25CB"; } /* ○ */

.railstep.done .railstep-ic { color:var(--ok); }
.railstep.done .railstep-ic::before { content:"\2713"; } /* ✓ */
.railstep.done .railstep-label { color:var(--ink); }

.railstep.current {
  background:rgba(217,48,37,.08);
  color:var(--ink);
  font-weight:700;
  box-shadow:inset 3px 0 0 var(--red);
}

.railstep.disabled {
  opacity:.45;
  cursor:not-allowed;
}
.railstep.disabled:hover { background:none; color:var(--muted); }

/* "coming soon" sits on its OWN line under the label, indented past the status
   glyph. At the rail's 208px a right-floated pill collided with the wrapped
   "Options & submit" label; giving it a full flex row keeps both legible. */
.railsoon {
  font-size:.58rem;
  background:#eee;
  color:var(--muted);
  border-radius:99px;
  padding:.08rem .4rem;
  flex:0 0 auto;
  margin:.15rem 0 0 1.6rem;
}
.railstep { flex-wrap:wrap; }
.railstep-label { flex:1 1 auto; min-width:0; }
/* horizontal strip (<1000px): keep each step on one line, pill inline again */
@media (max-width:1000px) {
  .railstep { flex-wrap:nowrap; }
  .railsoon { margin:0 0 0 .4rem; }
}

.railstep:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

@media (prefers-reduced-motion: reduce) {
  .railstep { transition:none; }
}

/* Below 1000px the rail stops being a left column and becomes a horizontal
   step strip ABOVE the content — this must trigger well before the
   Shielding page's own .shldgrid collapse (900px) so the rail never squeezes
   the 3D viewer on a laptop-width screen. */
@media (max-width:1000px) {
  .shell { display:block; }
  .rail {
    position:static;
    display:flex;
    align-items:center;
    gap:.4rem;
    overflow-x:auto;
    border-right:0;
    border-bottom:1px solid var(--line);
    padding:.6rem 0;
  }
  .rail-proj { display:none; }
  .railsteps { flex-direction:row; }
  .railstep { flex:none; white-space:nowrap; }
}

/* =====================================================================
   Phase 5 — Options & Submit page: constraints panel, "generate" job
   (reuses the ported .aiprog family from Phase 4, in-flow via .flow),
   three option cards, selected-option verify result, final summary,
   submitted-confirmation page.
   ===================================================================== */

/* ---------- .aiprog in-flow modifier (job progress panel, standalone) ---------- */

.aiprog.flow {
  position:static;
  left:auto;
  right:auto;
  bottom:auto;
  margin:1rem 0;
}

/* ---------- constraints panel ---------- */

.constraints {
  border:1px solid var(--line);
  border-top:2px solid var(--line);
  border-radius:12px;
  background:#fff;
  padding:1.1rem 1.2rem;
}

.congrid {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(11rem,1fr));
  gap:.8rem;
}

.confield {
  display:flex;
  flex-direction:column;
  gap:.25rem;
}

.confield input,
.confield select {
  width:100%;
  padding:.5rem .65rem;
  border:1px solid var(--line);
  border-radius:8px;
  font:inherit;
  color:var(--ink);
  background:#fff;
  cursor:pointer;
}
.confield input[type="text"],
.confield input[type="number"] {
  cursor:text;
}
.confield input:focus,
.confield select:focus {
  outline:none;
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.confield-hint {
  color:var(--muted);
  font-size:.75rem;
}

.confield.disabled {
  opacity:.55;
}
.confield.disabled input,
.confield.disabled select {
  background:#f1f2f4;
  cursor:not-allowed;
}

.consoon {
  font-size:.58rem;
  background:#eee;
  color:var(--muted);
  border-radius:99px;
  padding:.08rem .45rem;
  margin-left:.4rem;
  vertical-align:middle;
}

/* ---------- option cards (the 3 design options) ---------- */

.optgrid {
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));
  gap:1rem;
  margin:1rem 0;
}

.optcard {
  border:1.5px solid var(--line);
  border-radius:12px;
  padding:1rem 1.1rem;
  background:#fff;
  display:flex;
  flex-direction:column;
  gap:.55rem;
  position:relative;
  transition:border-color .15s;
}
.optcard:hover {
  border-color:#cdd7ea;
}
.optcard.selected {
  border-color:var(--red);
  box-shadow:0 0 0 2px rgba(217,48,37,.12);
}

.optcard-obj {
  font-weight:750;
  font-size:1.05rem;
  color:var(--ink);
}

.optcard-sum {
  font-size:.84rem;
  color:var(--muted);
  line-height:1.45;
  min-height:2.4em;
}

.optstats {
  display:grid;
  grid-template-columns:1fr auto;
  row-gap:.3rem;
  column-gap:.6rem;
  font-size:.85rem;
  margin-top:.2rem;
  border-top:1px solid var(--line);
  padding-top:.55rem;
}

.optstat-k {
  color:var(--muted);
}

.optstat-v {
  font-weight:700;
  font-variant-numeric:tabular-nums;
  text-align:right;
}

.optstat-v.good {
  color:var(--ok);
}

.optbadge {
  display:inline-block;
  font-size:.62rem;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.03em;
  border-radius:99px;
  padding:.12rem .5rem;
}
.optbadge.ok {
  background:#e6f3ea;
  color:var(--ok);
}
.optbadge.bad {
  background:#fdecea;
  color:var(--red);
}

.optlong {
  font-size:.8rem;
  color:#33415c;
  background:#f3f6fc;
  border:1px solid #cdd7ea;
  border-radius:8px;
  padding:.4rem .55rem;
  margin-top:.1rem;
}

.optlong-est {
  font-size:.58rem;
  text-transform:uppercase;
  letter-spacing:.04em;
  color:var(--muted);
  margin-left:.35rem;
}

.optnote {
  border:1px solid #e2c06b;
  background:#fdf6e3;
  color:#5c4a12;
  font-size:.78rem;
  border-radius:8px;
  padding:.4rem .55rem;
}

.optcard .btn {
  width:100%;
  justify-content:center;
  text-align:center;
  margin-top:auto;
}

/* ---------- verified-result block ---------- */

.verified {
  border:1.5px solid #cdd7ea;
  background:linear-gradient(180deg,#f6f8fc,#fff);
  border-radius:12px;
  padding:1rem 1.2rem;
  margin:1rem 0;
}

.verified-title {
  font-weight:750;
  margin-bottom:.5rem;
  display:flex;
  gap:.5rem;
  align-items:center;
  flex-wrap:wrap;
}

.verified-tag {
  border-radius:99px;
  padding:.14rem .55rem;
  font-size:.62rem;
  font-weight:700;
  text-transform:uppercase;
}
.verified-tag.true {
  background:#e6f3ea;
  color:var(--ok);
}
.verified-tag.cannot {
  background:#fdecea;
  color:var(--red);
}
/* M6: "for your review" — a neutral/informational tag distinct from the
   ok(green)/cannot(red) tags, matching the app's existing informational blue
   (see .optlong/.confirm's blue-gray palette). */
.verified-tag.proposal {
  background:#eef2fb;
  color:#33415c;
}

/* M6: restores quick.html's "first-pass proposal, review it" framing under the
   verified-title heading. */
.verified-intro {
  font-size:.85rem;
  color:var(--muted);
  margin:-.1rem 0 .7rem;
}

/* M4: ported from quick.html's needsHumanHtml — a softer amber twin of the red
   "Cannot redesign" callout, for features the vision AI couldn't confidently
   settle and flags for the engineer to confirm. */
.needshuman {
  border:1px solid #d9b46a;
  background:#fdf3dc;
  color:#7a5a1f;
  border-radius:8px;
  padding:.6rem .8rem;
  font-size:.9rem;
  margin:.5rem 0;
}

.cannotbox {
  border:1px solid #d98b8b;
  background:#fbecec;
  color:#7a2b2b;
  border-radius:8px;
  padding:.6rem .8rem;
  font-size:.88rem;
  margin:.5rem 0;
}
.cannotbox p {
  /* M4: the dose-ranked "kept open" finding renders as a <p> inside this box */
  margin:.4rem 0;
}
.cannotbox ul {
  margin:.3rem 0 0;
  padding-left:1.1rem;
}
.cannotbox li {
  margin:.15rem 0;
}

/* ---------- final summary + submit ---------- */

.finalsum h3 {
  font-size:.72rem;
  text-transform:uppercase;
  letter-spacing:.06em;
  color:var(--muted);
  font-weight:700;
  margin:1rem 0 .4rem;
}

.submitrow {
  margin-top:1.3rem;
  padding-top:1.1rem;
  border-top:1px solid var(--line);
}

.submitrow .btn {
  width:100%;
  justify-content:center;
  text-align:center;
}

.submitnote {
  font-size:.8rem;
  color:var(--muted);
  margin-top:.5rem;
  line-height:1.5;
}

/* ---------- confirmation page ---------- */

.confirm {
  border:1px solid #b7d9c1;
  background:#eef7f1;
  border-radius:12px;
  padding:2rem 1.5rem;
  text-align:center;
  margin:1.5rem 0;
}

.confirm-ic {
  font-size:2.2rem;
  line-height:1;
  color:var(--ok);
  margin-bottom:.5rem;
}

.confirm h2 {
  color:var(--ink);
  font-size:1.25rem;
  margin:0 0 .5rem;
}

.confirm p {
  color:#1a5c31;
  font-size:.9rem;
  margin:.35rem 0;
  line-height:1.55;
}

.confirm-actions {
  display:flex;
  gap:.7rem;
  justify-content:center;
  margin-top:1.1rem;
  flex-wrap:wrap;
}

/* ---------- Phase 5 responsive ---------- */

@media (max-width:640px) {
  .optgrid { grid-template-columns:1fr; }
  .congrid { grid-template-columns:1fr; }
  .verified-title { flex-direction:row; }
  .confirm-actions { flex-direction:column; align-items:stretch; }
  .confirm-actions .btn { width:100%; }
}

/* ---------- Phase 5 focus-visible ---------- */

.optcard .btn:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

.confield input:focus-visible,
.confield select:focus-visible {
  outline:2px solid var(--red);
  outline-offset:2px;
}

@media (prefers-reduced-motion: reduce) {
  .optcard { transition:none; }
}

/* =====================================================================
   Project overview page polish — live state-aware guidance bubble
   (replaces the stale, now-false .soonnote), a "Continue: <step> ->"
   primary button that agrees with it, breathing room around both plus a
   destructive-action separator, and an always-on autosaving Notes field.
   ===================================================================== */

/* ---------- .stepactions: bottom margin (append to the Phase-2 rule
   above — this rule only adds margin-bottom, it doesn't touch that
   selector's existing margin-top/padding-top/border-top) ---------- */

.stepactions {
  margin-bottom:1rem;
}

/* ---------- guidance speech bubble ---------- */

.guide {
  position:relative;
  margin:1.1rem 0 1.4rem;
  background:#f4f6f7;
  border:1px solid var(--line);
  border-radius:12px;
  padding:.8rem 1rem;
  font-size:.9rem;
  color:var(--ink);
}

/* Tail on the TOP edge, pointing up at the button in .stepactions above it.
   Two stacked triangles: ::before is the border colour, 1px larger and
   1px further up than ::after (the background colour on top of it), so the
   tail reads with the same hairline border as the rest of the bubble. */
.guide::before,
.guide::after {
  content:"";
  position:absolute;
  left:1.4rem;
  border-left:7px solid transparent;
  border-right:7px solid transparent;
}
.guide::before {
  top:-8px;
  border-bottom:8px solid var(--line);
}
.guide::after {
  top:-7px;
  border-bottom:7px solid #f4f6f7;
}

.guide.done {
  background:#eef7f1;
  border-color:#b7d9c1;
  color:#1a5c31;
}
.guide.done::before { border-bottom-color:#b7d9c1; }
.guide.done::after { border-bottom-color:#eef7f1; }

/* ---------- Notes card: "Saved" indicator ---------- */

.savedtag {
  font-size:.72rem;
  font-weight:650;
  color:var(--ok);
  opacity:0;
  transition:opacity .3s ease;
}
.savedtag.show { opacity:1; }

@media (prefers-reduced-motion: reduce) {
  .savedtag { transition:none; }
}

/* ---------- destructive-action row: divorced from the field above it ---------- */

.dangerrow {
  margin-top:2rem;
  border-top:1px solid var(--line);
  padding-top:1.2rem;
}

/* =====================================================================
   Mission page polish — spacing fix + the years/months duration editor's
   live end-date readout. Appended; the base .customorbit/.orbits rules
   above (Phase 2) are untouched.
   ===================================================================== */

/* ---------- custom-orbit panel: separate its dashed outline from the
   .orbits grid above it so the two never visually collide ---------- */

.customorbit {
  margin-top:1rem;
}

.orbits {
  margin-bottom:1rem;
}

/* ---------- live mission end-date readout (Mission timing section) ---------- */

.enddate {
  font-size:.85rem;
  color:var(--muted);
  margin-top:.4rem;
}
.enddate b {
  color:var(--ink);
  font-weight:700;
}

/* =====================================================================
   Phase 7 — accounts + persistence (Supabase). Sign-in view, save-state
   chrome (header savestate + user chip), the localStorage one-time import
   offer, and the stale-write conflict banner. Reuses the app's existing
   tokens (--red/--ink/--line/--muted/--ok) and .card/.btn/.field
   conventions — no new visual language.
   ===================================================================== */

/* ---------- header chrome: savestate + user chip (dark header, see
   .appheader in the Phase 1 section) ---------- */

.mg-chrome {
  display:flex;
  align-items:center;
  align-self:center;      /* .appheader aligns to baseline; the avatar must not */
  gap:.9rem;
}

.savestate {
  font-size:.78rem;
  font-weight:650;
  color:#c8ccd2;
  display:flex;
  align-items:center;
  gap:.35rem;
  min-height:1.2em;
}
.savestate:empty { display:none; }
.savestate.saving { color:#c8ccd2; }
.savestate.saved { color:#7ee2a8; }
.savestate.unsaved { color:#ffb4a8; }

.savestate-retry {
  border:1px solid #ff8a80;
  background:transparent;
  color:#ff8a80;
  border-radius:6px;
  font:inherit;
  font-size:.72rem;
  font-weight:700;
  padding:.1rem .5rem;
  cursor:pointer;
  line-height:1.3;
}
.savestate-retry:hover { background:rgba(255,138,128,.12); }
.savestate-retry:focus-visible { outline:2px solid #ff8a80; outline-offset:2px; }

/* ---------- account menu (header, signed in only) ---------- */

.acctmenu { position:relative; }

.acctbtn {
  display:flex;
  align-items:center;
  gap:.5rem;
  background:transparent;
  border:1px solid #4a4f57;
  border-radius:999px;
  padding:.28rem .6rem .28rem .32rem;
  font:inherit;
  font-size:.82rem;
  color:#c8ccd2;
  cursor:pointer;
  max-width:17rem;
  transition:border-color .12s ease, background .12s ease, color .12s ease;
}
.acctbtn:hover { border-color:#8a9099; color:#fff; background:rgba(255,255,255,.06); }
.acctbtn:focus-visible { outline:2px solid #fff; outline-offset:2px; }

.acctavatar {
  flex:0 0 auto;
  width:1.6rem;
  height:1.6rem;
  border-radius:50%;
  background:var(--red);
  color:#fff;
  font-size:.8rem;
  font-weight:700;
  display:flex;
  align-items:center;
  justify-content:center;
}
.acctemail {
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
.acctcaret { flex:0 0 auto; font-size:.7rem; opacity:.75; }

.acctdrop {
  position:absolute;
  top:calc(100% + .45rem);
  right:0;
  min-width:14rem;
  background:var(--card);
  border:1px solid var(--line);
  border-radius:10px;
  box-shadow:0 8px 24px rgba(0,0,0,.18);
  padding:.35rem;
  z-index:60;
}
.acctdrop[hidden] { display:none; }

.acctdrop-who {
  padding:.5rem .6rem .55rem;
  border-bottom:1px solid var(--line);
  margin-bottom:.35rem;
}
.acctdrop-label { font-size:.7rem; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); }
.acctdrop-email {
  font-size:.82rem;
  color:var(--ink);
  font-weight:600;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.acctitem {
  display:block;
  width:100%;
  text-align:left;
  background:transparent;
  border:0;
  border-radius:7px;
  padding:.5rem .6rem;
  font:inherit;
  font-size:.86rem;
  color:var(--ink);
  text-decoration:none;
  cursor:pointer;
}
.acctitem:hover { background:var(--bg); }
.acctitem:focus-visible { outline:2px solid var(--red); outline-offset:-2px; }
/* Sign out is destructive-adjacent and sits below a separator — it should not
   read as just another navigation row. */
.acctitem.danger { color:var(--red); font-weight:600; }
.acctitem.danger:hover { background:#fdecea; }

.acctdrop-sep {
  height:1px;
  background:var(--line);
  margin:.35rem -.35rem;
}

@media (max-width:640px) {
  .mg-chrome { gap:.5rem; padding-right:0; }
  .acctemail { display:none; }        /* avatar alone below 640px */
  .acctbtn { padding:.28rem .32rem; }
}

/* ---------- settings page ---------- */

.setcard { margin-bottom:1.1rem; }
.setcard-h {
  font-size:.95rem;
  font-weight:700;
  margin:0 0 .25rem;
}
.setcard-sub {
  color:var(--muted);
  font-size:.84rem;
  margin:0 0 1rem;
  line-height:1.5;
}
.setform { display:grid; gap:.9rem; max-width:26rem; }
.setform .form-actions { margin-top:.2rem; }
/* The read-only email sits outside .setform; match its measure so the column
   of inputs lines up instead of one field running the full card width. */
.setcard > .field { max-width:26rem; margin-bottom:.9rem; }
.setcard input[readonly] { background:var(--bg); color:var(--muted); cursor:default; }

.setmsg {
  font-size:.85rem;
  line-height:1.5;
  border-radius:8px;
  padding:.55rem .75rem;
  border:1px solid var(--line);
}
.setmsg.ok   { color:var(--ok);  background:#eaf6ec; border-color:#b7ddc0; }
.setmsg.err  { color:var(--red); background:#fdecea; border-color:#f0c9c4; }
.setmsg.warn { color:var(--ink); background:#fff4e0; border-color:#e2c06b; }

/* ---------- sign-in view ---------- */

.signin {
  display:flex;
  justify-content:center;
  padding:3rem 1rem;
}

.signin-card {
  width:100%;
  max-width:26rem;
  background:var(--card);
  border:1px solid var(--line);
  border-radius:14px;
  padding:2rem 1.8rem;
  text-align:center;
}

.signin-title {
  font-size:1.05rem;
  font-weight:800;
  letter-spacing:.02em;
  margin:0 0 .5rem;
}
.signin-title .labs { color:var(--red); }

.signin-sub {
  color:var(--muted);
  font-size:.88rem;
  margin:0 0 1.4rem;
  line-height:1.5;
}

.signin-form {
  display:grid;
  gap:.9rem;
  text-align:left;
}
.signin-form .form-actions {
  margin-top:.2rem;
}
.signin-form .btn.primary {
  width:100%;
  justify-content:center;
}

.signin-err {
  color:var(--red);
  font-size:.85rem;
  text-align:left;
  background:#fdecea;
  border:1px solid #f0c9c4;
  border-radius:8px;
  padding:.55rem .75rem;
}

/* Sign in / Create account segmented control. (The magic-link "check your
   email" state — .signin-sent — is gone: password auth returns a session
   synchronously, so there is no pending-delivery screen to style.) */

.signin-tabs {
  display:flex;
  gap:.3rem;
  background:var(--bg);
  border:1px solid var(--line);
  border-radius:10px;
  padding:.25rem;
  margin:0 0 1.3rem;
}
.signin-tab {
  flex:1 1 0;
  min-width:0;
  appearance:none;
  border:0;
  background:transparent;
  border-radius:7px;
  padding:.5rem .6rem;
  font:inherit;
  font-size:.85rem;
  font-weight:600;
  color:var(--muted);
  cursor:pointer;
  transition:background .12s ease, color .12s ease;
}
.signin-tab:hover { color:var(--ink); }
.signin-tab.on {
  background:var(--card);
  color:var(--ink);
  box-shadow:0 1px 2px rgba(0,0,0,.09);
}
.signin-tab:focus-visible { outline:2px solid var(--red); outline-offset:1px; }

/* Accepted-but-not-usable outcome (signup with no session back). Deliberately
   NOT .signin-err red — nothing failed; the account just isn't live yet. */
.signin-notice {
  font-size:.85rem;
  text-align:left;
  line-height:1.5;
  color:var(--ink);
  background:#fff4e0;
  border:1px solid #e2c06b;
  border-radius:8px;
  padding:.6rem .75rem;
}

.signin-hint {
  margin:1.1rem 0 0;
  font-size:.78rem;
  line-height:1.55;
  color:var(--muted);
  text-align:left;
}

/* ---------- stale-write conflict banner (persists across route changes —
   inserted as a sibling of .shell, see renderStaleConflictBanner) ---------- */

.staleconflict {
  background:#fff4e0;
  border:1px solid #e2c06b;
  border-left:5px solid var(--red);
  padding:.7rem 1.2rem;
  display:flex;
  align-items:center;
  gap:1rem;
  flex-wrap:wrap;
}
.staleconflict-msg {
  flex:1;
  min-width:16rem;
  font-size:.88rem;
  color:#5c4a12;
}
.staleconflict-actions {
  display:flex;
  gap:.6rem;
  flex-wrap:wrap;
}

@media (max-width:640px) {
  .staleconflict { padding:.7rem 1rem; }
  .staleconflict-msg { min-width:0; }
  .signin-card { padding:1.5rem 1.2rem; }
}

/* Numeric fields read as numbers, not prose. A full-bleed input for a 2-3 digit
   krad value looked like a free-text box (the field IS type=number — it always
   rejected letters — but nothing on screen said so). Constrain the measure and
   keep the spinners visible so the affordance matches the behaviour. */
.numfield input[type="number"] {
  max-width:12rem;
  font-variant-numeric:tabular-nums;
}

/* ---------------------------------------------------------------- Phase 7.1
   Give the CAD viewer the room it deserves. The shielding page previously split
   its width roughly in half, so the 3D model — the thing the engineer is
   actually reading — sat at ~600px with the controls column stretched wide to
   fill space it didn't need. Mirror /quick's proportions instead: a fixed
   control column and the viewer taking everything left over. The 208px step
   rail is the extra constraint /quick doesn't have, so the page also widens. */
.wrap.wide { max-width:1400px; }
.shldgrid { grid-template-columns:360px minmax(0,1fr); }
@media (max-width:1100px) {
  /* rail is still a column here; keep the viewer from being crushed */
  .shldgrid { grid-template-columns:320px minmax(0,1fr); }
}
@media (max-width:900px) {
  .shldgrid { grid-template-columns:1fr; }   /* (already stacks; kept explicit) */
}

/* ---------- background-job notification (outside #app: survives every route
   render, because a job finishes while you are on some other page) ---------- */

#mg-jobnotices { display:flex; flex-direction:column; }

.jobnotice {
  display:flex;
  align-items:center;
  gap:1rem;
  flex-wrap:wrap;
  padding:.7rem 1.2rem;
  border-bottom:1px solid var(--line);
  font-size:.88rem;
}
.jobnotice.ok  { background:#eaf6ec; border-left:5px solid var(--ok); color:#16301c; }
.jobnotice.err { background:#fdecea; border-left:5px solid var(--red); color:#3a1714; }
.jobnotice-msg { flex:1; min-width:14rem; line-height:1.45; }
.jobnotice-actions { display:flex; align-items:center; gap:.5rem; }
.jobnotice-x {
  appearance:none;
  border:0;
  background:transparent;
  font-size:1.15rem;
  line-height:1;
  padding:.2rem .4rem;
  cursor:pointer;
  color:inherit;
  opacity:.65;
  border-radius:6px;
}
.jobnotice-x:hover { opacity:1; background:rgba(0,0,0,.07); }
.jobnotice-x:focus-visible { outline:2px solid currentColor; outline-offset:1px; }

/* "you can leave this page" — the queued state must not imply you must wait */
.runhint {
  font-size:.82rem;
  color:var(--muted);
  line-height:1.5;
  margin-top:.5rem;
  background:var(--bg);
  border:1px dashed var(--line);
  border-radius:8px;
  padding:.55rem .75rem;
}
.runhint b { color:var(--ink); }

/* Hardware Input drops its pagehead, so the grid starts at the top of the page */
.shldgrid.tight { margin-top:.25rem; }

/* ---------- Options & submit: the review of exactly what gets sent ---------- */

.revlead {
  color:var(--muted);
  font-size:.86rem;
  line-height:1.55;
  margin:.1rem 0 1rem;
  max-width:46rem;
}
.review {
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(15rem, 1fr));
  gap:.9rem;
  margin-bottom:1.4rem;
}
.revcard {
  background:var(--card);
  border:1px solid var(--line);
  border-radius:12px;
  padding:.9rem 1rem;
  min-width:0;
}
.revcard h3 {
  font-size:.72rem;
  text-transform:uppercase;
  letter-spacing:.05em;
  color:var(--muted);
  margin:0 0 .6rem;
  font-weight:700;
}
.revcard.revnotes { grid-column:1 / -1; }
.revrow {
  display:flex;
  justify-content:space-between;
  gap:.9rem;
  padding:.3rem 0;
  border-bottom:1px dotted var(--line);
  font-size:.85rem;
}
.revrow:last-child { border-bottom:0; }
.revk { color:var(--muted); flex:0 0 auto; }
.revv {
  font-weight:600;
  text-align:right;
  min-width:0;
  overflow-wrap:anywhere;
}
.revnotetext {
  margin:0;
  font-size:.87rem;
  line-height:1.6;
  white-space:pre-wrap;
  overflow-wrap:anywhere;
}
.revnotetext.dim { color:var(--muted); font-style:italic; }

/* Compact page head for Hardware Input: keeps the step title (and the back
   link above it) without giving back the vertical space the CAD viewer and
   design inputs were moved up into. */
.pagehead.tight { margin-bottom:.55rem; }
.pagehead.tight h1 { font-size:1.2rem; margin:0 0 .1rem; }
.pagehead.tight .sub { font-size:.84rem; }

/* ---------- password reveal toggle ---------- */

.pwwrap { position:relative; display:block; }
/* Reserve room so a long password never runs under the button */
.pwwrap input { width:100%; padding-right:2.6rem; }

.pwtoggle {
  position:absolute;
  top:50%;
  right:.45rem;
  transform:translateY(-50%);
  display:flex;
  align-items:center;
  justify-content:center;
  width:1.9rem;
  height:1.9rem;
  padding:0;
  border:0;
  border-radius:7px;
  background:transparent;
  color:var(--muted);
  cursor:pointer;
  transition:color .12s ease, background .12s ease;
}
.pwtoggle:hover { color:var(--ink); background:var(--bg); }
.pwtoggle:focus-visible { outline:2px solid var(--red); outline-offset:1px; color:var(--ink); }
/* Revealed reads as "on", so the state is visible without hovering */
.pwtoggle[aria-pressed="true"] { color:var(--red); }
.pwtoggle svg { display:block; pointer-events:none; }

/* Project-level controls (Notes, Delete) relocated onto Mission Parameters
   when the overview page was removed. Set apart so they don't read as part of
   the mission form above them. */
.projadmin {
  margin-top:2rem;
  padding-top:1.2rem;
  border-top:1px solid var(--line);
}
