:root {
  --surface: #fcfcfb; --page: #f4f4f1; --ink: #0b0b0b; --ink2: #52514e; --muted: #898781;
  --line: #e1e0d9; --blue: #2a78d6; --orange: #eb6834; --aqua: #1baf7a; --red: #d03b3b;
  --warn-bg: #fff6e0; --err-bg: #fdecec;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--page); color: var(--ink);
  font: 14px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif; }
header { display: flex; align-items: center; gap: 16px; padding: 10px 16px; background: var(--surface);
  border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.brand { font-weight: 700; font-size: 18px; white-space: nowrap; }
.brand .logo { color: var(--blue); }
.brand .sub { font-weight: 400; font-size: 13px; color: var(--ink2); margin-left: 6px; }
.search { position: relative; flex: 1 1 320px; min-width: 240px; }
.search input { width: 100%; padding: 8px 10px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
.hits { position: absolute; z-index: 30; top: 40px; left: 0; right: 0; max-height: 380px; overflow: auto;
  background: #fff; border: 1px solid #c3c2b7; border-radius: 6px; box-shadow: 0 6px 24px rgba(0,0,0,.12); }
.hit { padding: 8px 10px; border-bottom: 1px solid var(--line); cursor: pointer; }
.hit:hover, .hit:focus { background: #eef4fc; outline: none; }
.hit .id { font-weight: 600; }
.hit .d { color: var(--ink2); font-size: 12.5px; }
.actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
button, .button, select { font: inherit; border-radius: 6px; padding: 7px 12px; cursor: pointer;
  border: 1px solid #c3c2b7; background: #fff; color: var(--ink); }
button.primary { background: var(--blue); border-color: var(--blue); color: #fff; font-weight: 600; }
button.primary:disabled { opacity: .55; cursor: progress; }
.ghost { background: #fff; }
main { height: calc(100% - 58px); }
#editor { position: relative; border-right: 1px solid var(--line); }
#blockly { position: absolute; inset: 0; }
#results { overflow: auto; padding: 14px 16px 40px; }
.status { padding: 10px 12px; background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  color: var(--ink2); margin-bottom: 12px; }
.status.busy::before { content: ""; display: inline-block; width: 10px; height: 10px; margin-right: 8px;
  border: 2px solid var(--blue); border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px;
  margin-bottom: 12px; }
.card h3 { margin: 0 0 6px; font-size: 15px; display: flex; gap: 8px; align-items: center; }
.card h3 .chip { font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 10px; color: #fff; }
.card p { margin: 4px 0; color: var(--ink2); }
.card.error { border-color: #e7a4a4; background: var(--err-bg); }
.warn { background: var(--warn-bg); border-left: 3px solid #eda100; padding: 6px 10px; margin: 6px 0;
  font-size: 13px; color: #5a4300; }
.tablewrap { overflow-x: auto; margin-top: 8px; }
table { border-collapse: collapse; font-size: 12.5px; width: 100%; }
th, td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--ink2); font-weight: 600; background: #f7f7f4; position: sticky; top: 0; }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbtools { display: flex; gap: 8px; margin-top: 6px; }
.tbtools button { padding: 3px 9px; font-size: 12.5px; }
#figbox { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; }
.figbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.figbar h2 { margin: 0; font-size: 16px; }
.figtools { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; font-size: 13px; }
.figtools input { width: 84px; padding: 4px 6px; border: 1px solid #c3c2b7; border-radius: 5px; font: inherit; }
.figtools button { padding: 4px 9px; font-size: 13px; }
.tracksel { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 8px 0; font-size: 12.5px; color: var(--ink2); }
#figure { overflow-x: auto; }
#figure svg { display: block; }
.tip { position: fixed; z-index: 50; pointer-events: none; background: #0b0b0b; color: #fff; font-size: 12px;
  padding: 6px 8px; border-radius: 5px; max-width: 340px; line-height: 1.35; }
@media (max-width: 900px) {
  #analysis, #figurebuild { grid-template-columns: 1fr; grid-template-rows: 60vh auto; height: auto; }
  #editor { height: 60vh; border-right: 0; border-bottom: 1px solid var(--line); }
  .palette { border-right: 0; border-bottom: 1px solid var(--line); max-height: 180px; }
}

/* ------------------------------------------------------------------ tabs & pages */
.tabs { display: flex; gap: 4px; }
.tab { background: #f1f1ed; border: 1px solid var(--line); font-weight: 600; color: var(--ink2); }
.tab.on { background: var(--blue); border-color: var(--blue); color: #fff; }
.page { display: none; }
.page.on { display: grid; }
#analysis { grid-template-columns: minmax(420px, 46%) 1fr; height: calc(100vh - 58px); }
#figurebuild { grid-template-columns: 240px 1fr; height: calc(100vh - 58px); }
#lab { grid-template-columns: 1fr; height: calc(100vh - 58px); overflow: auto; }

/* ------------------------------------------------------------------ figure builder */
.palette { border-right: 1px solid var(--line); background: var(--surface); overflow: auto; padding: 10px; }
.phead { font-size: 12px; color: var(--ink2); margin: 8px 0 6px; font-weight: 600; }
.chip { background: #eef4fc; border: 1px solid #cfe0f6; border-radius: 6px; padding: 6px 8px; margin-bottom: 6px;
  font-size: 12.5px; cursor: grab; user-select: none; }
.chip:hover { background: #e3edfb; }
.chip.used { opacity: .55; }
.chip.float { background: #f6f1ff; border-color: #ded2f6; }
.figwrap { overflow: auto; padding: 12px 16px 60px; position: relative; }
.hint { color: var(--ink2); font-size: 12.5px; margin: 6px 0 10px; }
.figure { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  min-height: 220px; padding: 4px 0; }
.stack { position: relative; }
.lane { position: relative; cursor: grab; }
.lane:hover { background: #f6f8fc; }
.lane.over { box-shadow: inset 0 3px 0 var(--blue); }
.lane svg { display: block; }
.lanetools { position: absolute; right: 6px; top: 2px; display: none; gap: 2px; }
.lane:hover .lanetools { display: flex; }
.lanetools button { padding: 0 6px; font-size: 12px; line-height: 18px; border-radius: 4px; }
.floatbox { position: absolute; cursor: move; padding: 2px 4px; border-radius: 4px; }
.floatbox:hover { outline: 1px dashed var(--blue); }
.floatbox span[contenteditable] { outline: none; }
/* The ✕ used to sit 22px outside the box, so the pointer crossed dead space on the way to it,
   the box stopped being :hover, and the button vanished from under the cursor. It now sits in
   reserved padding inside the box, the same trick the grip uses, and stays while it has focus
   so the keyboard can reach it. */
.floatbox .fx { visibility: hidden; position: absolute; right: 1px; top: 0; padding: 0 5px; font-size: 11px; }
.floatbox:hover .fx, .floatbox .fx:focus-visible { visibility: visible; }
.legend { display: flex; flex-wrap: wrap; gap: 10px; font-size: 11px; color: var(--ink2); }
.legend .lg { display: inline-flex; align-items: center; gap: 4px; }
.legend .sw { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }

/* ------------------------------------------------------------------ lab notebook */
.labwrap { padding: 14px 18px 60px; max-width: 1360px; display: grid;
  grid-template-columns: 250px minmax(0, 1fr); gap: 18px; align-items: start; }
.labmain { min-width: 0; }
@media (max-width: 900px) { .labwrap { grid-template-columns: 1fr; } }

/* ---- the folder browser */
.labtree { background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 8px 6px 4px; position: sticky; top: 14px; }
.treebar { display: flex; align-items: center; gap: 4px; padding: 0 6px 6px; font-size: 13px;
  border-bottom: 1px solid var(--line); }
.treebar button { font-size: 11.5px; padding: 3px 6px; }
.treebody { max-height: 64vh; overflow: auto; padding: 4px 0; }
.fnode { display: flex; align-items: center; gap: 4px; padding: 3px 6px; border-radius: 5px;
  font-size: 12.5px; cursor: pointer; white-space: nowrap; }
.fnode:hover { background: #f1f1ed; }
.fnode.on { background: #e4eefb; color: #11498f; font-weight: 600; }
.fnode.drop { box-shadow: inset 0 0 0 2px var(--blue); }
.fnode .tw { width: 12px; flex: none; color: var(--muted); font-size: 10px; }
.fnode .ic { flex: none; }
.fnode .nm { overflow: hidden; text-overflow: ellipsis; flex: 1; }
.fnode .ct { color: var(--muted); font-size: 11px; flex: none; }
.fnode .tacts { display: none; gap: 2px; flex: none; }
.fnode:hover .tacts { display: flex; }
.fnode .tacts button { border: none; background: none; padding: 0 3px; font-size: 11px; color: var(--ink2); }
.fnode .tacts button:hover { color: var(--blue); }
.fnode.bait .ic { color: var(--muted); font-size: 9px; }
.fnode.dragging { opacity: .45; }
/* the root of the tree: it is what "no folder" looks like, so it has to read as a row you
   can select, but not as another folder sitting alongside the real ones */
.fnode.top { color: var(--ink2); border-bottom: 1px solid var(--line); border-radius: 5px 5px 0 0;
  margin-bottom: 2px; }
.fnode.top .ic { color: var(--muted); }
.treehint { margin: 6px 6px 2px; line-height: 1.35; }
.labbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.labbar .byname { font-size: 12px; color: var(--ink2); }
.labbar input, .labbar select { padding: 6px 8px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
.spacer { flex: 1; }
.muted { color: var(--ink2); }
.small { font-size: 12px; }
.grouphead { margin: 16px 0 6px; font-size: 13px; color: var(--ink2); text-transform: uppercase; letter-spacing: .04em; }
.bait { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; margin-bottom: 8px; padding: 8px 10px; }
.bait.open { border-color: #b9d2f3; box-shadow: 0 2px 10px rgba(42,120,214,.08); }
.baithead { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.twist { border: none; background: none; font-size: 13px; padding: 0 2px; }
.pctnum { font-variant-numeric: tabular-nums; color: var(--ink2); font-size: 12.5px; }
.bar { display: flex; gap: 3px; margin: 7px 0 2px; }
.bar .seg { flex: 1; text-align: center; font-size: 10.5px; padding: 3px 2px; border-radius: 4px;
  background: #ececeb; color: #8a8a85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar .in_progress { background: #fde8c9; color: #7a5200; }
.bar .done { background: #d4ecd6; color: #11651c; }
.bar .failed { background: #f8d7d7; color: #8f1d1d; }
.baitbody { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 8px; }
.stagerow { display: grid; grid-template-columns: 170px 130px 1fr; gap: 8px; align-items: center; margin-bottom: 5px; }
.stagerow .sname { font-size: 12.5px; color: var(--ink); cursor: help; }
.stagerow select, .stagerow input { padding: 4px 6px; border: 1px solid #c3c2b7; border-radius: 5px; font: inherit; font-size: 12.5px; }
.baitacts { display: flex; gap: 8px; margin: 10px 0; }
.baitacts .danger { color: #a12020; border-color: #e0b4b4; }
.primerform h4, .baitbody h4 { margin: 14px 0 4px; font-size: 13.5px; }
.primerform label { display: block; font-size: 12.5px; color: var(--ink2); margin-bottom: 6px; }
.primerform input { width: 100%; padding: 6px 8px; border: 1px solid #c3c2b7; border-radius: 6px;
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; }
.primerform .row { display: flex; gap: 8px; margin: 8px 0; }
.presult { margin-top: 6px; }
.suggestpanel { border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; margin: 6px 0; }
.suggestpanel p { margin: 6px 0 4px; }
.ptable { border-collapse: collapse; font-size: 12px; margin: 4px 0; width: 100%; }
.ptable th, .ptable td { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line); vertical-align: top; }
.ptable th { font-weight: 600; color: var(--ink2); }
.ptable .mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; overflow-wrap: anywhere; }
.askline { background: #fdf6e7; border-left: 3px solid #e0a93a; padding: 6px 8px; margin: 8px 0 4px; font-size: 12.5px; }
.prow { margin-bottom: 6px; }
.tag { background: #e7e0fb; color: #3c2a86; border-radius: 10px; padding: 1px 7px; font-size: 11px; font-weight: 600; }
.okline { color: #11651c; background: #eef7ef; border-left: 3px solid #1baf7a; padding: 4px 8px; margin: 4px 0; font-size: 12.5px; }
.saved { border: 1px solid var(--line); border-radius: 6px; padding: 6px 8px; margin-bottom: 6px; }
.seqline { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; color: var(--ink2);
  overflow-wrap: anywhere; }
.seqline span { display: inline-block; width: 14px; color: var(--blue); font-weight: 700; }
.maps { display: flex; gap: 12px; flex-wrap: wrap; }
.mapcard { border: 1px solid var(--line); border-radius: 8px; padding: 8px; background: #fff; }
.maphead { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; font-size: 12.5px; }
.button.small, .ghost.small { padding: 2px 8px; font-size: 11.5px; text-decoration: none; }
dialog { border: 1px solid var(--line); border-radius: 10px; padding: 16px; }
.floatbox { pointer-events: none; }
.floatbox > * { pointer-events: auto; }
/* the grip sits in reserved space outside the flow: if it appeared on hover it would push
   the box's contents sideways, and a click aimed at a legend button would miss it */
.floatbox { padding-left: 16px; padding-right: 20px; }
.floatbox .grip { position: absolute; left: 1px; top: 2px; visibility: hidden; cursor: move;
  color: var(--muted); font-size: 11px; }
.floatbox:hover .grip { visibility: visible; }
/* the legend is built by hand, so its controls must take clicks while the box itself
   still lets a click through to the row underneath */
.floatbox .legend, .floatbox .legend * { pointer-events: none; }
.floatbox .legend input, .floatbox .legend span[contenteditable],
.floatbox .legend .lgx, .floatbox .legend .lgadd { pointer-events: auto; }

/* ---- figure: empty canvas, lane resize grip, worked-example dialog */
.figempty { border: 1.5px dashed var(--line); border-radius: 8px; padding: 22px 18px; margin: 4px;
  color: var(--ink2); font-size: 13px; line-height: 1.5; background: #fcfcfb; }
.lanegrab { position: absolute; left: 0; right: 0; bottom: -3px; height: 7px; cursor: ns-resize; }
.lane:hover .lanegrab { background: linear-gradient(transparent, rgba(42,120,214,.22)); }
.figtools label { font-size: 12px; color: var(--ink2); }
.figtools label input { width: 58px; }
dialog.big { max-width: min(960px, 94vw); max-height: 90vh; overflow: auto; }
dialog.big h3 { margin: 0 0 8px; font-size: 15px; }
dialog.big menu { margin: 12px 0 0; padding: 0; display: flex; justify-content: flex-end; }
.exfig { border: 1px solid var(--line); border-radius: 8px; overflow: auto; margin: 10px 0; background: #fcfcfb; }
.exfig svg { display: block; max-width: 100%; height: auto; }
.exkey { display: grid; grid-template-columns: 170px 1fr; gap: 4px 12px; margin: 6px 0 0; font-size: 12.5px; }
.exkey dt { font-weight: 600; color: var(--ink); }
.exkey dd { margin: 0; color: var(--ink2); }

/* ---- primers: the tail is printed on the form, the student types only the rest */
.tailed { display: flex; align-items: stretch; border: 1px solid #c3c2b7; border-radius: 6px; overflow: hidden;
  background: #fff; }
.tailed .tail { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11.5px; padding: 6px 7px;
  background: #eef2f8; color: #3a5d8f; border-right: 1px dashed #b9c6da; white-space: nowrap; cursor: help; }
.tailed input { border: 0 !important; border-radius: 0 !important; flex: 1; min-width: 120px; }

/* ---- the cloning bench */
.bench { border: 1px solid var(--line); border-radius: 8px; padding: 10px; margin: 12px 0; background: #fcfcfb; }
.bench.solved { border-color: #bfe3cd; background: #f6fbf7; }
.bench.waiting { opacity: .62; }
.benchhead { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.benchhead .spacer { flex: 1; }
.tag.ok { background: #d9f0e1; color: #11651c; }
.bsetup { margin: 4px 0 8px; }
.tray { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 7px; border-radius: 6px;
  background: #f1f0ea; margin-bottom: 8px; }
.traylabel { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
  margin-right: 2px; }
.part { border: 1px solid #c3c2b7; background: #fff; border-radius: 13px; padding: 3px 10px; font-size: 12px;
  cursor: grab; user-select: none; }
.part.insert { border-color: #eb6834; color: #a8431c; font-weight: 600; }
.part.used { opacity: .34; cursor: default; }
.trow { display: grid; grid-template-columns: 210px 1fr; gap: 8px; align-items: center; margin-bottom: 6px; }
.trow .tname { font-size: 12.5px; color: var(--ink2); }
.slots { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.slot { min-width: 104px; text-align: center; border: 1.5px dashed #c3c2b7; border-radius: 13px; padding: 3px 10px;
  font-size: 12px; color: var(--muted); background: #fff; }
.slot.filled { border-style: solid; border-color: #8a8a85; color: var(--ink); cursor: pointer; }
.slot.over { border-color: var(--blue); background: #eef4fd; }
.slot.good { border-color: #1baf7a; background: #eef7ef; color: #11651c; }
.slot.bad { border-color: #d05a5a; background: #fdf0f0; color: #8d2020; }
.benchout { margin-top: 6px; }
.hintline { background: #fff8e6; border-left: 3px solid #e0a93a; padding: 4px 8px; margin: 4px 0; font-size: 12.5px; }
.mapcard.locked { opacity: .75; }
.lockmsg { width: 240px; font-size: 12px; color: var(--muted); padding: 22px 10px; text-align: center; }

/* ---- figure builder: palette categories, per-piece tags, style inspector */
.pcat { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
  margin: 10px 0 3px; font-weight: 600; }
.palette .chip { display: flex; align-items: center; gap: 6px; }
.palette .chip .sw { width: 11px; height: 11px; border-radius: 2px; flex: none; }
.lane.sel { background: #eef4fd; box-shadow: inset 2px 0 0 var(--blue); }
.lanetags { position: absolute; left: 4px; bottom: 1px; display: none; flex-wrap: wrap; gap: 3px; }
.lane:hover .lanetags, .lane.sel .lanetags { display: flex; }
.itag { display: inline-flex; align-items: center; gap: 4px; background: #fff; border: 1px solid var(--line);
  border-radius: 10px; padding: 0 4px 0 5px; font-size: 10.5px; cursor: pointer; line-height: 15px; }
.itag.on { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue); }
.itag .sw { width: 8px; height: 8px; border-radius: 2px; }
.itag button { border: 0; background: none; cursor: pointer; font-size: 9px; color: var(--muted); padding: 0 1px; }
.newlane { border: 1.5px dashed var(--line); border-radius: 6px; margin: 4px; padding: 7px; text-align: center;
  color: var(--muted); font-size: 11.5px; background: var(--surface); position: relative; z-index: 2; }
.newlane.over { border-color: var(--blue); background: #eef4fd; color: var(--blue); }
.inspect { position: sticky; bottom: 0; border: 1px solid var(--blue); border-radius: 8px; background: #fff;
  padding: 8px 10px; margin: 6px 0 0; box-shadow: 0 -2px 8px rgba(0,0,0,.06); }
.ihead { display: flex; align-items: center; font-weight: 600; font-size: 12.5px; margin-bottom: 5px; }
.ihead button { margin-left: auto; }
.irow { display: grid; grid-template-columns: 90px 1fr 34px; gap: 8px; align-items: center; margin-bottom: 3px; }
.irow label { font-size: 12px; color: var(--ink2); }
.irow .ival { font-size: 11.5px; color: var(--muted); text-align: right; }
.sws { display: flex; gap: 3px; flex-wrap: wrap; align-items: center; }
.swbtn { width: 16px; height: 16px; border-radius: 3px; border: 1px solid rgba(0,0,0,.18); cursor: pointer; padding: 0; }
.swbtn.on { outline: 2px solid var(--blue); outline-offset: 1px; }
.sws input[type=color] { width: 22px; height: 18px; padding: 0; border: 1px solid var(--line); background: none; }
.legend .lg { display: inline-flex; align-items: center; gap: 3px; margin-right: 8px; }
.legend .lg input[type=color] { width: 16px; height: 14px; padding: 0; border: 0; background: none; }
.legend .lg span[contenteditable] { font-size: 11px; }
.legend .lgx { border: 0; background: none; cursor: pointer; font-size: 9px; color: var(--muted); }
.lgadd { border: 1px dashed var(--line); background: #fff; border-radius: 10px; font-size: 10.5px;
  padding: 1px 7px; cursor: pointer; margin-right: 4px; color: var(--ink2); }

/* ---- admin tab */
.adminwrap { padding: 14px 16px; overflow: auto; }
.admbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.admbar .spacer { flex: 1; }
.admgrid { display: grid; grid-template-columns: 1fr 1.3fr; gap: 12px; align-items: start; }
.adminwrap .card { border: 1px solid var(--line); border-radius: 8px; background: #fff; padding: 12px 14px;
  margin-bottom: 12px; }
.adminwrap .card h3 { margin: 0 0 6px; font-size: 14px; }
.adminwrap pre { background: #f1f0ea; padding: 8px; border-radius: 6px; font-size: 11.5px; overflow: auto; }
/* ---- sequencing: a plasmid against what came back from the sequencer

   The base rows are the point, so they get a real monospace grid and one colour per call.
   Everything above them exists to stop anyone having to read the rows at all unless a
   difference actually landed somewhere that matters. */
.seqwrap { padding: 12px 14px; overflow: auto; height: 100%; }
.seqbar { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start;
  border: 1px solid var(--line); border-radius: 8px; background: #fff; padding: 10px 12px; margin-bottom: 10px; }
.seqpick { display: grid; gap: 5px; font-size: 12.5px; min-width: 250px; }
.seqpick b { font-size: 12.5px; }
.seqpick label { display: flex; align-items: center; gap: 5px; }
.seqpick select { max-width: 330px; padding: 4px 6px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; font-size: 12px; }
.seqgo { display: grid; gap: 7px; align-content: start; margin-left: auto; }
.sqpaste textarea { width: 330px; font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 11px; padding: 5px; border: 1px solid #c3c2b7; border-radius: 6px; resize: vertical; }
.sqout { margin-top: 10px; }

.sqverdict { display: grid; gap: 2px; padding: 9px 12px; border-radius: 8px; margin-bottom: 10px;
  border: 1px solid var(--line); background: #faf9f5; }
.sqverdict span { font-size: 12px; color: #5d5c52; }
.sqverdict.ok { background: #eef7ec; border-color: #bcd9b6; }
.sqverdict.warn { background: #fdf6e7; border-color: #e3d2a4; }
.sqverdict.bad { background: #fdf0f0; border-color: #e0b4b4; }

.sqstrip { width: 100%; height: 74px; display: block; margin-bottom: 8px; }
.sqlegend { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 11.5px;
  color: #5d5c52; margin: 6px 0 10px; }
.sqlegend .spacer { flex: 1; }
.sqlegend label { display: flex; align-items: center; gap: 4px; }
.op, .sqlegend i.op { display: inline-block; width: 10px; height: 10px; border-radius: 2px; vertical-align: -1px; }
.op.m { background: #cfe3c9; } .op.x { background: #c0392b; } .op.i { background: #c77d23; }
.op.d { background: #2a74b8; } .op.u { background: #d8d6cd; }

.sqsec { border: 1px solid var(--line); border-radius: 8px; background: #fff; margin-bottom: 10px; }
.sqsec > summary { cursor: pointer; padding: 7px 11px; font-size: 12.5px; font-weight: 600; }
.sqsec > *:not(summary) { padding: 0 11px 11px; }
.sqtab { width: 100%; border-collapse: collapse; font-size: 12px; }
.sqtab th { text-align: left; font-weight: 600; color: #5d5c52; border-bottom: 1px solid var(--line); padding: 4px 6px; }
.sqtab td { padding: 3px 6px; border-bottom: 1px solid #eeede7; }
.sqtab td.num { text-align: right; font-variant-numeric: tabular-nums; }
.sqtab td.mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; word-break: break-all; max-width: 220px; }
.sqtab tr.hasdiff { background: #fdf6f6; }
.sqtab tr.sqjump { cursor: pointer; }
.sqtab tr.sqjump:hover { background: #f1f0ea; }
.fdot { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }

.sqbases { overflow-x: auto; }
.sqrow { margin: 0 0 9px; border-radius: 4px; }
.sqrow.flash { animation: sqflash 1.2s ease-out; }
@keyframes sqflash { from { background: #fdf0c8; } to { background: transparent; } }
/* the track shares the base rows' font so its ch unit is the same width as a base cell */
.ftrack { position: relative; height: 15px; margin-left: 140px;
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; line-height: 1; }
/* flex, not an inline span: the track carries a 12px font so the ch unit matches a base
   cell, and an inline label inherited that baseline and hung half of itself below the bar,
   where overflow:hidden cut it off */
.fbar { position: absolute; top: 2px; height: 11px; border-radius: 2px; opacity: 0.85;
  overflow: hidden; display: flex; align-items: center; }
.fbar span { font-size: 8.5px; line-height: 1; color: #fff; padding: 0 3px; white-space: nowrap; }
.sline { display: flex; align-items: baseline; font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.35; }
.sline .gut { width: 72px; flex: none; text-align: right; padding-right: 8px; color: #8a897e;
  font-size: 10.5px; font-variant-numeric: tabular-nums; }
.sline .lbl { width: 60px; flex: none; font-size: 10px; color: #8a897e; text-align: right;
  padding-right: 8px; font-family: system-ui, sans-serif; }
.sline code { white-space: pre; }
/* the match ticks are scaffolding: the bases are what is being read */
.sline.mid .b.m { color: #c8c6bd; }
.sline .b { display: inline-block; width: 1ch; }
.sline .b.m { color: #3a3a33; }
.sline .b.x { background: #c0392b; color: #fff; }
.sline .b.i { background: #c77d23; color: #fff; }
.sline .b.d { background: #2a74b8; color: #fff; }
.sline .b.u { background: #ecebe4; color: #b3b2a8; }

/* ---- add a bait by hand */
#baitdlg { max-width: min(680px, 94vw); }
#baitdlg h3 { margin: 0 0 10px; font-size: 15px; }
.bdgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px 10px; margin: 8px 0; }
.bdgrid label, .bdseqlab { display: block; font-size: 12.5px; }
#baitdlg input, #baitdlg select, #baitdlg textarea {
  width: 100%; padding: 5px 7px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
#baitdlg textarea { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11.5px;
  resize: vertical; word-break: break-all; }
.bdrow { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
.bdhits { display: grid; gap: 4px; margin: 6px 0; max-height: 170px; overflow: auto; }
.bdhit { display: grid; gap: 1px; text-align: left; padding: 5px 7px; font: inherit; font-size: 12px;
  background: #faf9f5; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; }
.bdhit:hover { background: #f1f0ea; }
.bdhit span { font-size: 11.5px; color: #5d5c52; }
#baitdlg menu { margin: 12px 0 0; padding: 0; display: flex; justify-content: flex-end; gap: 8px; }

/* ---- signing in: the same shape as the admin login card, but in the header's dialog */
#sidlg { max-width: 400px; }
#sidlg h3 { margin: 0 0 6px; font-size: 15px; }
#sidlg label { display: block; margin: 10px 0; font-size: 13px; }
#sidlg input { width: 100%; padding: 6px 8px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
#sidlg menu { margin: 14px 0 0; padding: 0; display: flex; justify-content: flex-end; gap: 8px; }
#who { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.card.login { max-width: 420px; }
.card.login label { display: block; margin: 8px 0; font-size: 13px; }
.card.login input { width: 100%; padding: 6px 8px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
.kv { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 3px 0;
  border-bottom: 1px solid var(--line); }
.kv:last-child { border-bottom: 0; }
.ok { color: #11651c; font-weight: 600; }
.bad { color: #a12020; font-weight: 600; }
.runout { margin-top: 8px; }
.tres { font-size: 12px; margin: 4px 0; }
.tres summary { cursor: pointer; }
.f2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 10px; }
.adminwrap label { display: block; font-size: 12.5px; color: var(--ink2); margin-bottom: 6px; }
.adminwrap label.inline { display: inline-flex; align-items: center; gap: 5px; }
.adminwrap input:not([type=checkbox]), .adminwrap select { width: 100%; padding: 5px 7px; border: 1px solid #c3c2b7;
  border-radius: 6px; font: inherit; font-size: 12.5px; }
.adminwrap .row { display: flex; gap: 8px; align-items: center; margin: 8px 0; flex-wrap: wrap; }
.cand { border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; margin-bottom: 8px; }
.cand.approved { border-color: #9cc6f0; background: #f6faff; }
.cand.installed { border-color: #bfe3cd; background: #f6fbf7; }
.candhead { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.candhead .spacer { flex: 1; }
.candhead .state { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.candtitle { font-size: 12.5px; margin: 3px 0; }
.snap { display: flex; align-items: center; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--line);
  font-size: 12.5px; }
.snap .spacer { flex: 1; }
@media (max-width: 1100px) { .admgrid { grid-template-columns: 1fr; } }

/* lab notebook: matches for the Find box that live in other projects */
.elsewhere { margin-top: 18px; border-top: 1px dashed #d4d2cc; padding-top: 10px; }
.findhit { display: flex; gap: 10px; align-items: baseline; width: 100%; text-align: left;
  margin: 3px 0; padding: 6px 10px; }
.findhit:hover { background: #f0efea; }
.findhit span:last-child { margin-left: auto; }

/* lab notebook: the inline "really delete this?" panel, with the admin password when needed */
.delbox:empty { display: none; }
.delpanel { margin: 8px 0 2px; padding: 10px 12px; border: 1px solid #e0b4ad; border-radius: 8px;
  background: #fdf5f3; }
.delpanel .row { margin-top: 8px; gap: 8px; }
.delpanel .pwline { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.delpanel .pwline input { flex: 0 0 220px; }

/* ------------------------------------------------------------------ buttons feel pressed
   Before this a button looked identical whether you were over it, holding it down or not
   touching it, which made the page feel unresponsive. Hover lifts, holding presses in, and
   keyboard focus shows a ring. */
button, .button, .tab, .chip { transition: background-color .12s ease, border-color .12s ease,
  box-shadow .12s ease, color .12s ease, transform .04s ease; }
button:hover, .button:hover { background: #f0efea; border-color: #a8a79c; }
button:active, .button:active { background: #e3e2da; border-color: #94938a; transform: translateY(1px);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15); }
button.primary:hover { background: #2169bd; border-color: #2169bd; }
button.primary:active { background: #1a5596; border-color: #1a5596; }
.tab:hover { background: #e6e6e0; border-color: #c6c5bb; }
.tab.on:hover, .tab.on:active { background: #2169bd; border-color: #2169bd; color: #fff; }
.danger:hover { background: var(--err-bg); border-color: #d99; color: #a12020; }
.danger:active { background: #f8dcdc; border-color: var(--red); }
.chip:active { transform: translateY(1px); box-shadow: inset 0 2px 4px rgba(0, 0, 0, .12); }

/* a visible ring for anyone driving the page from the keyboard */
button:focus-visible, .button:focus-visible, .tab:focus-visible, .chip:focus-visible,
input:focus-visible, select:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

button:disabled, button:disabled:hover, button:disabled:active {
  opacity: .55; cursor: not-allowed; transform: none; box-shadow: none;
  background: #fff; border-color: #c3c2b7; }
button.primary:disabled, button.primary:disabled:hover, button.primary:disabled:active {
  background: var(--blue); border-color: var(--blue); color: #fff; cursor: progress; }

/* A save hands over a file and leaves nothing on screen, so the button says so for a moment. */
button.done, .button.done, button.done:hover, button.done:active {
  background: #e5f4e4; border-color: var(--aqua); color: #0f6b4a; transform: none; box-shadow: none; }

/* lab notebook: one step back after a delete or a re-cut */
.labundo { display: flex; gap: 10px; align-items: center; margin: 6px 0 2px;
  padding: 6px 10px; border: 1px solid #e0d7ad; border-radius: 8px; background: var(--warn-bg); }

/* lab notebook: results of designing primers for a whole project at once */
.labbatch { margin: 8px 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); }
.labbatch .mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; }
.labbatch table { font-size: 12px; }

/* ------------------------------------------------------------------ the guides */
/* Both tutorials are markdown (web/guide.md and server/admin_guide.md), rendered by
   guide.js. These rules dress the result as prose rather than as app furniture: one
   readable column, and tables and code that look the same in either guide. */
#guide { grid-template-columns: 250px minmax(0, 1fr); height: calc(100vh - 58px); }
.gtoc { border-right: 1px solid var(--line); background: var(--surface); overflow: auto;
  padding: 10px 8px 40px; }
.gtoc input { width: 100%; padding: 6px 8px; border: 1px solid #c3c2b7; border-radius: 6px; font: inherit; }
.gtoc #guidecount { margin: 4px 2px 6px; min-height: 14px; }
.gtoc a { display: block; padding: 4px 7px; border-radius: 5px; color: var(--ink2); text-decoration: none;
  font-size: 12.5px; line-height: 1.3; }
.gtoc a.sub { padding-left: 18px; font-size: 12px; color: var(--muted); }
.gtoc a:hover { background: #eef4fc; color: var(--ink); }
.gtoc a.on { background: #eef4fc; color: var(--ink); font-weight: 600; }
.guidewrap { overflow: auto; padding: 4px 28px 120px; }
.prose { max-width: 820px; }
.prose h1 { font-size: 23px; margin: 22px 0 6px; }
.prose h2 { font-size: 18px; margin: 0 0 10px; padding-top: 22px; }
.prose h3 { font-size: 15px; margin: 18px 0 4px; }
.prose h4 { font-size: 13.5px; margin: 14px 0 2px; color: var(--ink2); }
.prose p, .prose li { color: var(--ink2); }
.prose p { margin: 8px 0; }
.prose ul, .prose ol { margin: 8px 0; padding-left: 22px; }
.prose li { margin: 4px 0; }
.prose li > ul { margin: 2px 0; }
.prose b { color: var(--ink); }
.prose code { background: #f0efe9; border: 1px solid var(--line); border-radius: 4px; padding: 0 3px;
  font-size: 12.5px; }
.prose pre { background: #f7f7f4; border: 1px solid var(--line); border-radius: 6px; padding: 9px 11px;
  overflow-x: auto; }
.prose pre code { background: none; border: 0; padding: 0; font-size: 12.5px; }
.prose table { background: var(--surface); }
.prose th { position: static; }
.prose .tablewrap { margin: 10px 0; border: 1px solid var(--line); border-radius: 6px; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 20px 0; }
.prose a { color: var(--blue); }
/* a section is the unit the contents list points at and the find box filters */
.gsec { border-top: 1px solid var(--line); margin-top: 6px; }
.gsec:first-of-type { border-top: 0; }
/* the admin guide folds, because it is dipped into rather than read */
details.gsec { padding: 2px 0; }
details.gsec > summary { cursor: pointer; font-size: 15px; font-weight: 700; padding: 8px 2px; }
details.gsec > summary:hover { color: var(--blue); }
details.gsec[open] > summary { margin-bottom: 4px; }
.admguide { max-width: 820px; }
@media (max-width: 900px) {
  #guide { grid-template-columns: 1fr; grid-template-rows: auto 1fr; height: auto; }
  .gtoc { border-right: 0; border-bottom: 1px solid var(--line); max-height: 180px; }
  .guidewrap { padding: 4px 14px 60px; }
}
