/* The look of the shared Create DNA Constructs overlay, and of the paste-and-review upload that
   sits in the same kind of box.

   These rules were on the binders page, where the overlay was. When the overlay moved to a
   partial the markup went with it and the styling did not, so the targets page rendered it
   INLINE at the bottom of the page: `.overlay` was undefined there, so nothing was fixed,
   nothing was dimmed, and `.step` did not hide the steps you were not on. It read as a broken
   page rather than a missing stylesheet -- which is exactly how this failed the last time, with
   the upload wizard.

   TOP-LEVEL RULES ONLY. Everything inside an @media block stayed where it was: the first
   attempt at this lifted rules out of one and left it with an opening brace and no rule.
*/

.overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.overlay.open { display: flex; }
.overlay-box { background: var(--white); border-radius: 12px; padding: 32px; width: 700px; max-height: 85vh; overflow-y: auto; box-shadow: 0 20px 60px rgba(0,0,0,0.3); }
.overlay-box h2 { font-size: 20px; font-weight: 700; margin-bottom: 20px; color: var(--dark-navy); }

.step { display: none; }
.step.active { display: block; }
.pg-link { color: var(--pink); text-decoration: none; font-weight: 600; }
.pg-link:hover { text-decoration: underline; }
.pg-disabled { color: var(--border-light); font-weight: 600; }
.overlay-box.paged .pv-head { flex: 0 0 auto; }
.overlay-box.paged .pv-body { flex: 1 1 auto; overflow: auto; min-height: 0; }
.fmt-options { display: flex; gap: 12px; margin-bottom: 16px; }
.fmt-card { flex: 1; border: 2px solid var(--border-light); border-radius: 10px; padding: 14px 16px; cursor: pointer; transition: all 0.15s; }
.fmt-card.selected { border-color: var(--pink); background: rgba(236,58,148,0.04); }
.fmt-card h4 { font-size: 14px; font-weight: 700; color: var(--dark-navy); margin: 0 0 4px; }
.fmt-card p { font-size: 12px; color: var(--grey-text); margin: 0; }
.tag-row { display: grid; grid-template-columns: 90px 1fr 1fr; gap: 12px; align-items: center; margin-bottom: 10px; }
.tag-row label.part-label { font-weight: 600; font-size: 13px; color: var(--dark-navy); }
.tag-col-head { display: grid; grid-template-columns: 90px 1fr 1fr; gap: 12px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; color: var(--grey-text); font-weight: 600; margin-bottom: 6px; }
.seqml .chain-label { display: inline-block; font-family: inherit; font-weight: 700; color: var(--grey-text); font-size: 10px; margin: 4px 6px 2px 0; text-transform: uppercase; letter-spacing: 0.3px; }
.seg { padding: 1px 0; border-radius: 2px; }
.seg-tag { background: #EDE7F6; color: #4527A0; box-shadow: inset 0 -2px 0 #B39DDB; }
.seg-binder { background: #FCE4EC; color: #880E4F; box-shadow: inset 0 -2px 0 #F48FB1; }
.seg-chip { display: inline-block; font-size: 9px; font-weight: 700; background: #4527A0; color: #fff; border-radius: 3px; padding: 0 4px; margin: 0 2px; vertical-align: middle; letter-spacing: 0.2px; }
.cn-table { width: 100%; border-collapse: collapse; }
.cn-table th { background: #fafafa; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; padding: 8px 10px; text-align: left; font-weight: 600; border-bottom: 2px solid var(--border-light); }
.cn-table td { padding: 10px; border-bottom: 1px solid var(--border-light); font-size: 13px; vertical-align: top; }
.cn-table .row-num { color: var(--grey-text); width: 36px; }
.cn-fixed td, .cn-fixed th { overflow-wrap: anywhere; }
.tagdd-trigger:hover { border-color: var(--pink); }
.tagdd-trigger.open { border-color: var(--pink); }
.tagdd-meta:empty { display: none; }

.tagdd-trigger .material-icons { font-size: 18px; color: var(--grey-text); margin-left: auto; }
.tagdd-trigger.placeholder .tagdd-t-label { color: var(--grey-text); }
.tagdd-search-wrap { padding: 10px 12px; border-bottom: 1px solid var(--border-light); }
.tagdd-search { width: 100%; padding: 6px 10px; font-size: 13px; border: 1px solid var(--border-light);
  border-radius: 6px; font-family: inherit; }
.tagdd-search:focus { outline: none; border-color: var(--pink); }
.tagdd-item { display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
  border: none; background: none; padding: 7px 9px; border-radius: 6px; cursor: pointer;
  font-family: inherit; }
.tagdd-item:hover { background: rgba(236,58,148,0.06); }
.tagdd-item.selected { background: rgba(236,58,148,0.10); }
.tagdd-item-name { flex: 1; min-width: 0; max-width: 70%; }
.tagdd-item.selected .tagdd-main { color: var(--pink); }
.tagdd-sub { display: block; font-size: 11px; color: var(--grey-text); margin-top: 1px; overflow-wrap: anywhere; }
.tagdd-flags { display: flex; flex-direction: column; gap: 3px; align-items: flex-end;
  flex-shrink: 0; padding-top: 1px; max-width: 30%; }

.tagdd-flag { font-size: 9.5px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase;
  border-radius: 999px; padding: 1px 7px; white-space: nowrap; }
.tagdd-flag.opt     { background: #f1f2f5; color: #6b7280; }
.tagdd-item.pipe-item .pipe-name { flex-wrap: wrap; row-gap: 6px; }
.tagdd-item.pipe-item.selected .pipe-val { color: var(--pink); }
.tagdd-trigger .pipe-val { white-space: normal; }
.tagdd-sub .tagdd-cat { font-size: 10px; padding: 0 4px; }
.tagdd-legend { padding: 7px 12px; border-top: 1px solid var(--border-light); font-size: 10.5px;
  color: var(--grey-text); line-height: 1.5; }
.tagdd-empty { padding: 12px; font-size: 12px; color: var(--grey-text); }
.tagdd-installed .material-icons { font-size: 13px; color: var(--grey-text); flex: none; }
.tagdd-installed span:last-child { overflow-wrap: anywhere; }
.cn-cat-toggle[hidden] { display: none; }
.cn-cat-btn { font-family: inherit; font-size: 12px; font-weight: 700; padding: 6px 13px;
  border: none; border-radius: 7px; background: transparent; color: var(--grey-text); cursor: pointer; }
.cn-cat-btn:hover:not(.active) { color: var(--dark-navy); background: rgba(0,0,0,0.04); }
.cn-cat-btn.active { background: var(--pink); color: #fff; }
.cn-sys-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-primary); font-size: 12.5px; font-weight: 600;
  padding: 5px 11px; border-radius: 16px; cursor: pointer;
  border: 2px solid var(--border-light); background: var(--white); color: var(--dark-navy);
  transition: border-color 0.15s, background 0.15s;
}
.cn-sys-pill.active { border-color: var(--pink); background: rgba(236,58,148,0.06); color: var(--pink); }
.cn-sys-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px;
  background: var(--pink); color: #fff; font-size: 10px; font-weight: 700;
}


/* ── Moved from manage_binders.html, second pass ───────────────────────────────────────────
   The first pass took 61 rules and left the rest, so /targets drew the overlay with its
   structure and none of its controls: the tag and vector pickers rendered as bare boxes
   because `.tagdd-trigger` itself was still on the binders page -- only its :hover and .open
   variants had travelled. The box was never `.wide` either, so everything inside it was
   squeezed into the 700px default.

   The lesson from the first pass, repeated: a partial's CSS ships WITH the partial. Anything
   the shared overlay draws with belongs here, not on one of the two pages that include it.
   TOP-LEVEL RULES ONLY; no @media block was opened.
*/
/* Binder-type segmented toggle */
/* binder-type pill in the groups table */
.type-pill { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 11px; background: #EEF; color: #445; border: 1px solid #DDE; white-space: nowrap; max-width: 100%; }
/* In the Type column the pill has a column width to live inside, and "Antibody (mAb, Fab, scFv)"
   is wider than it: the pill wraps onto two lines rather than spilling into Target. Elsewhere
   (the construct overlay's header) it sits in open space and stays on one line.

   At SPACES only -- the cell's `overflow-wrap: anywhere` would otherwise break the label
   mid-word. "Single-domain" carries a non-breaking hyphen for the same reason: it fits the
   column easily and has no business splitting across two lines to prove it. */
#groups-table .type-pill { white-space: normal; overflow-wrap: normal; }
/* Paged overlay: header + scrollable body + pager pinned to the box (not scrolling) */
.overlay-box.paged { display: flex; flex-direction: column; overflow: hidden; }
.pager { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-top: 14px; margin-top: 10px; border-top: 1px solid var(--border-light); font-size: 13px; color: var(--grey-text); }
.pager:empty { display: none; }

/* Create DNA Constructs dialog */
.overlay-box.wide { width: 1040px; max-width: 95vw; }
/* A grid item's min-width defaults to auto, i.e. its MIN-CONTENT width. The trigger's chips are
   nowrap and flex-shrink:0, so their combined min-content width let the 1fr columns grow past
   their share and pushed the whole overlay sideways. Nothing here needs to be wider than its
   track. */
.tag-row > * { min-width: 0; }
/* All selects + text inputs in the Create-DNA-Constructs overlay share one consistent box. */
#construct-overlay select, #construct-overlay input[type="text"] { width: 100%; box-sizing: border-box; height: 38px; padding: 7px 10px; border: 1px solid var(--border-light); border-radius: 6px; font-size: 13px; background: #fff; font-family: var(--font-primary); color: var(--dark-navy); }

/* AA_SeqML rendered segments */
.seqml { font-family: 'Monaco','Menlo',monospace; font-size: 11px; line-height: 1.7; word-break: break-all; }
/* Fixed-width construct table: columns sized per colgroup, table scrolls when it overflows */
.cn-fixed { table-layout: fixed; min-width: 1180px; }
/* Tag/linker picker. Built on the kebab-menu popover (body-mounted, one open at a time, same
   outside-click close) because .overlay-box scrolls -- an in-flow panel gets clipped by it.
   Styling follows the org-dropdown in catalog_targets.html: a select-shaped trigger, a panel
   with a search box, and rows carrying a main line, a sub line and right-aligned meta. */
.tagdd-trigger { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0;
  max-width: 100%;
  padding: 8px 10px; border: 1px solid var(--border-light); border-radius: 8px;
  background: var(--white); font-size: 13px; color: var(--dark-navy); cursor: pointer;
  text-align: left; font-family: inherit; }
/* The name WRAPS instead of being clipped -- these names carry the information that tells two
   parts apart ("(3'-tgag)" vs "(3'-Gibson to pET28)"), and an ellipsis cuts exactly that off.
   It now has the trigger to itself: the pills moved to their own line below, where the whole row
   width is available instead of whatever the name leaves over. */
.tagdd-trigger .tagdd-t-label { flex: 1 1 auto; min-width: 0;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }

/* The pills, under the control. Wraps, so a long catalog number plus two flags simply takes a
   second line rather than widening the grid track. */
.tagdd-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px;
  margin: 4px 2px 0; min-width: 0; }

/* FIXED, not absolute. The trigger lives inside .overlay-box, which is its own scroll container
   (max-height:85vh; overflow-y:auto) sitting in a position:fixed backdrop. An absolutely
   positioned menu is placed against the DOCUMENT, so it rode the page behind the overlay and
   drifted away from the trigger it belonged to. Fixed coordinates plus a reposition on scroll
   keep it attached to the control instead. */
/* Width is set per-open from the trigger it belongs to (see _placeTagMenu), so the menu lines up
   with the control instead of being a fixed 460px that is too narrow for a long part name and too
   wide for a short row. */
.tagdd-menu { position: fixed; z-index: 2000; background: #fff; border: 1px solid var(--border-light);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.16); padding: 0; width: 460px;
  max-width: calc(100vw - 24px); display: flex; flex-direction: column; }
/* The list scrolls itself, and `contain` stops that scroll chaining into the overlay (and then
   the page) once it hits an end -- which is what made the wheel feel like it was moving the
   wrong thing. max-height is also set per-open from the room actually available. */
.tagdd-list { overflow-y: auto; max-height: 340px; padding: 4px; overscroll-behavior: contain; }
/* Both are spans, so `margin-top` on the sub did nothing and the catalogue number ran straight
   into the name -- "pGZ1418(Amp)pGZ1418(Amp)_pcDNA3.4_hs_IGHA1". They are two lines. */
.tagdd-main { display: block; font-size: 13px; font-weight: 600; color: var(--dark-navy); overflow-wrap: anywhere; }
/* A flag that carries a PART NAME rather than a piece of vocabulary. "Pre-made" and "Fixed NT"
   are labels and read fine shouted; a name does not -- TwinStrep, IgKC, BsaI and scFv all carry
   meaning in their capitalisation, and TWINSTREP / IGKC throw that away and are slower to read
   besides. Same pill, same weight, the case the part actually has. */
.tagdd-flag.named { text-transform: none; letter-spacing: .1px; font-size: 10px; font-weight: 600; }
/* A nucleotide overhang: monospace, because it is read base by base. */
.tagdd-flag.seq { font-family: 'Monaco','Menlo',monospace; font-size: 9.5px; letter-spacing: .3px; }
/* Pre-made: exists as a catalogued part, joined on rather than synthesized for this order. */
.tagdd-flag.premade { background: #EAF7EE; color: #2E7D32; }
/* Fixed NT: the nucleotides are given, so the organism choice does not codon-optimize them. */
.tagdd-flag.fixed   { background: #EAF0FB; color: #1565C0; }
/* A pipeline row: the KV pills fill the whole row rather than sitting in the name/flags split a
   part uses. They wrap, because four pairs side by side are wider than a dropdown. */
.tagdd-item.pipe-item { display: block; padding: 9px 10px; }
/* In the closed trigger the pills must not set the control's height or push the chevron off. */
.tagdd-trigger .pipe-name { flex-wrap: wrap; row-gap: 4px; }
/* What this pipeline recommends -- the option the form opens on. */
.tagdd-flag.rec     { background: #FDF0F6; color: #B0186B; }
/* Catalog number: monospace, because it is an identifier to be read and quoted, not prose. */
.tagdd-cat { font-family: 'Monaco','Menlo',monospace; font-size: 10.5px; font-weight: 700;
  color: var(--dark-navy); background: #f1f2f5; border-radius: 4px; padding: 0 5px;
  white-space: nowrap; flex-shrink: 0; border: 0; }
/* Only the one under the control is clickable -- it is the chosen part, and there is a single
   unambiguous map to open. The copies inside the menu list are labels, not buttons. */
button.tagdd-cat { cursor: pointer; font-family: 'Monaco','Menlo',monospace; }
button.tagdd-cat:hover { background: rgba(236,58,148,0.12); color: var(--pink); }
/* An end the backbone occupies: shown, not offered. Deliberately not styled as a disabled
   control -- there is no choice being withheld, the part is simply already there. */
.tagdd-installed { display: flex; align-items: center; gap: 6px; min-width: 0;
  padding: 7px 10px; border: 1px dashed var(--border-light); border-radius: 8px;
  background: #FAFBFC; font-size: 12.5px; color: var(--dark-navy); }
/* The installed-content chips carry names as long as "CAR TM-CoStim - CD28 TM + CD28 CoStim", so
   they wrap instead of forcing the grid track wider than its share. */
.tagdd-flag { overflow-wrap: anywhere; white-space: normal; }
.gv-spin { display:inline-block; animation: gv-spin 0.8s linear infinite; }
.nt-skel { height: 34px; border-radius: 8px; margin-bottom: 6px;
  background: linear-gradient(90deg, #F1F2F5 25%, #E7E9EE 37%, #F1F2F5 63%);
  background-size: 200% 100%; animation: nt-shimmer 1.2s linear infinite; }
/* One choice of seed. Same vocabulary as .fmt-card, sized for a list rather than two columns. */
.nt-src { display:flex; gap:10px; align-items:flex-start; border:2px solid var(--border-light);
  border-radius:10px; padding:10px 12px; cursor:pointer; margin-bottom:6px; transition:all .15s; }
.nt-src.selected { border-color: var(--pink); background: rgba(236,58,148,0.04); }
.nt-src .material-icons { font-size:18px; color:var(--grey-text); flex:none; margin-top:1px; }
.nt-src.selected .material-icons { color: var(--pink); }
.nt-src b { font-size:13px; color:var(--dark-navy); display:block; }
.nt-src small { font-size:11.5px; color:var(--grey-text); }

/* Expression-system pills above the pipeline select — same two-level choice as the front page
   and the project wizard, so a pipeline is picked the same way everywhere. */
.cn-sys-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
/* Second layer of the pipeline choice: Binding vs Protein Characterization. Same segmented
   control as the project wizard's `.wiz-cat-toggle`, so the three-level narrowing
   (system -> category -> pipeline) looks and behaves identically wherever a pipeline is picked. */
.cn-cat-toggle { display: inline-flex; width: fit-content; margin: 0 0 8px; padding: 3px; gap: 3px;
  background: #f1f1f4; border-radius: 9px; }

/* Phone width. Moved WHOLE, block and all -- the last attempt lifted rules out of an
   @media and left it with an opening brace and no rule. */
/* ── Stacked rows (matches .table.stackable in base.html, 760px) ──────────────
   Placed last so it wins over the wide-table rules above. */
@media (max-width: 760px) {
  /* Overlays use the full width of a phone rather than a 32px-inset card. */
  .overlay-box { padding: 18px; width: 100%; max-width: 100%; }
  .overlay-box.wide { width: 100%; max-width: 100%; }

  /* `.cn-table` is width:100%, which on a phone crushed the Sequence column to about 60px --
     the monospace blocks wrapped one short run per line and were clipped mid-residue. A protein
     sequence cannot usefully narrow, so the table keeps a workable width and scrolls inside the
     overlay (which is already overflow:auto) instead. */
  .cn-table { min-width: 560px; }
  .cn-table td, .cn-table th { padding: 8px; }
}
