/* The console's own styling.
 *
 * app.css is what both pages share and what the selector needs; this is the
 * part only the console uses -- the tab bar, the editors, the grids, the
 * sign-in page, the importer, the flow and canvas editors, the version
 * history. It was all in one file, which meant every visitor downloaded the
 * console's stylesheet to look at a product list: 42 KB of the 145, for rules
 * that could never match anything on their page.
 *
 * Only admin.html loads this one. A rule belongs here when nothing outside
 * the console's own modules uses its class -- tools/csssplit.mjs is the check
 * that says so, and it is run against both files rather than trusted.
 */
/* The card that turns it on wears a little of the mark itself, so it is not
   one more checkbox in a column of checkboxes. */
.testcard { border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }

/* Twelve pages in a row is a wall. Four groups, each a short button that opens
   the pages inside it. */
.tabgroup { position: relative; }
/* One row, centred: the picker does not stretch to the bar's height, and
   nothing in it breaks into a column of single characters. */
#app .tabs { align-items: center; flex-wrap: wrap; row-gap: 4px; }
#app .tabs > * { flex-shrink: 0; }
#app .tabs .spacer { flex: 1 1 0; min-width: 8px; }
#app .tabs .linepick { max-width: 280px; text-overflow: ellipsis; }
.tabgroup .tabbtn, .rolechip, .acctname { white-space: nowrap; }
/* The account menu: name and role on the bar, its actions inside. */
.tabgroup.acct .tabbtn { align-items: center; gap: 7px; font-size: 13px; color: var(--ink-2); }
.tabgroup.acct .acctname { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.tabmenu.right { left: auto; right: 0; }
/* Which product line or solution the page is about: a line of its own under
   the menus, so the menus keep one row. */
.scopebar { display: flex; align-items: center; gap: 10px; margin: -8px 0 14px; }
.scopelbl { font-size: 12px; color: var(--ink-3); white-space: nowrap; }
.scopebar .linepick { margin-right: 0; max-width: 420px; }
/* On a narrower screen feedback and the manual keep their icon, not their word. */
@media (max-width: 1240px) { #app .tabs .docbtn .lbl { display: none; } }
.tabgroup .tabbtn {
  display: flex; align-items: baseline; gap: 7px; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabgroup .tabbtn .gname { font-weight: 560; }
.tabgroup .tabbtn .gcaret { font-size: 10px; color: var(--ink-3); }
.tabgroup .tabbtn:hover { color: var(--ink); }

.tabmenu {
  display: none; position: absolute; left: 0; top: calc(100% + 4px); z-index: 40;
  min-width: 168px; padding: 5px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 8px 24px rgba(0, 0, 0, .13);
}
.tabmenu button {
  display: block; width: 100%; text-align: left; padding: 7px 11px; border-radius: var(--r-md);
  font-size: 13.5px; border-bottom: 0; margin-bottom: 0;
}
.tabmenu button:hover { background: var(--surface-2); color: var(--ink); }
/* Small headings inside the settings menu. */
.tabsub {
  padding: 9px 11px 3px; font-size: 11px; font-weight: 650; letter-spacing: .04em;
  color: var(--ink-3); text-transform: uppercase;
}
.tabsub:first-child { padding-top: 4px; }
/* 待辦: a plain tab, not a menu. */
.homebtn { white-space: nowrap; font-weight: 560; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.homebtn.on { color: var(--brand); border-bottom-color: var(--brand); }

/* The finder: one box that reaches every page, card and field. */
.finder { position: relative; margin-left: 24px; min-width: 200px; max-width: 360px; flex: 1 1 260px; }
.finder[hidden] { display: none; }
.finder input {
  width: 100%; padding: 6px 64px 6px 30px; border-radius: var(--r-pill); font-size: 13px;
  background: var(--surface-2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23889' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E") no-repeat 10px 50%;
}
.finder kbd {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%); pointer-events: none;
  font: 10.5px/1 var(--mono); color: var(--ink-3); border: 1px solid var(--line); border-radius: 4px; padding: 2px 4px;
}
.finder input:focus + kbd { display: none; }
.finder-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 60; min-width: 300px;
  padding: 5px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 10px 28px rgba(0, 0, 0, .16); max-height: 60vh; overflow: auto;
}
.finder-row {
  display: flex; flex-direction: column; align-items: flex-start; width: 100%; text-align: left;
  padding: 7px 10px; border-radius: var(--r-md); border: 0; background: none; cursor: pointer; gap: 1px;
}
.finder-row.on, .finder-row:hover { background: var(--brand-soft); }
.finder-label { font-size: 13.5px; color: var(--ink); }
.finder-path { font-size: 11.5px; color: var(--ink-3); }
.finder-none { padding: 10px; font-size: 13px; color: var(--ink-3); }
/* Where the finder landed: a short glow, then nothing. */
.found { animation: found 2.4s ease-out; }
@keyframes found {
  0%, 30% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 45%, transparent); }
  100% { box-shadow: 0 0 0 3px transparent; }
}

/* 待辦 */
.homegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; margin: 4px 0 10px; }
.homeitem {
  display: flex; align-items: center; gap: 12px; text-align: left; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); cursor: pointer;
}
.homeitem:hover { border-color: var(--brand); background: var(--brand-soft); }
.homeitem.warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.homen { font: 650 22px/1 var(--mono); color: var(--brand); min-width: 34px; text-align: center; }
.homeitem.warn .homen { color: var(--warn); }
.hometxt { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.hometxt small { color: var(--ink-3); font-size: 12px; }
.homego { font-size: 12.5px; color: var(--brand); white-space: nowrap; }
.homedone { color: var(--ok); font-size: 14px; margin: 4px 0 12px; }
.homeshort { display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 720px) { .finder { margin-left: 10px; min-width: 0; } .finder kbd { display: none; } }
.tabmenu button[aria-selected="true"] {
  color: var(--brand); font-weight: 560; background: var(--brand-soft);
  border-bottom-color: transparent;
}
.grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 14px; }

/* One row per thing the model does: a switch, a name, and the sentence that
   says what turning it off takes away. */
.aidoes { display: grid; gap: 4px; margin: 6px 0 12px; }
.aidoe { align-items: flex-start; padding: 8px 10px; border-radius: var(--radius); }
.aidoe:hover { background: var(--surface-2); }
.aidoe span { display: flex; flex-direction: column; gap: 2px; }
.aidoe small { color: var(--ink-2); font-size: 12px; line-height: 1.5; }

/* The report, shown inside the console. It is rendered by the same code that
   writes the emailed one, so it brings its own colours: this only gives it a
   frame and stops its white cards glowing in dark mode. */
.repbody { border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.repbody h1 { font-size: 17px; margin: 0 0 4px; }
.repbody h2 { font-size: 14px; margin: 0 0 10px; color: var(--brand); }
.repbody table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.repbody th, .repbody td { text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--line); }
.repbody .sum { white-space: pre-wrap; line-height: 1.7; }

/* The word list: a button per word, sized by nothing and weighted by a bar
   behind it -- a word cloud lies about magnitude, a bar does not. */
.askwords { display: flex; flex-wrap: wrap; gap: 6px; }
.askword {
  position: relative; display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 11px; border-radius: var(--r-pill); font: inherit; font-size: 13px;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink);
  cursor: pointer; overflow: hidden;
}
.askword::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: var(--w, 0);
  background: color-mix(in srgb, var(--brand) 16%, transparent);
}
.askword span { position: relative; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.askword:hover { border-color: var(--brand); }

/* The security page. The cap bar is the only chart here: one measure, one
   hue, with the number beside it. */
.gcap { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.gcap .ut { flex: 1 1 auto; height: 10px; border-radius: var(--r-sm); background: var(--surface-2); overflow: hidden; }
.gcap .ut i { display: block; height: 100%; border-radius: var(--r-sm); background: var(--brand); }
.gcap span { font-variant-numeric: tabular-nums; font-size: 13px; color: var(--ink-2); }
.glimits { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: 12px; }
.gadd { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 14px; }
.gadd input { flex: 1 1 180px; min-width: 140px; }
.gkinds { margin: 0 0 10px; }

/* The usage report. Every list here is one measure -- how many -- so the bars
   are one hue and each row carries its own number: nothing has to be read off
   an axis, and the bar is there to show the shape of the list at a glance. */
.uhead { display: flex; align-items: flex-start; gap: 12px; margin: 0 0 14px; }
.utiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; }
.utile {
  display: flex; flex-direction: column; gap: 2px; padding: 14px;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-2);
}
.utile .ulabel { font-size: 12.5px; color: var(--ink-2); }
.utile strong { font-size: 26px; font-variant-numeric: tabular-nums; line-height: 1.2; }
.utile .unote { font-size: 11.5px; color: var(--ink-3); }
.ubar {
  display: grid; grid-template-columns: minmax(120px, 1fr) minmax(80px, 2fr) auto;
  align-items: center; gap: 10px; padding: 5px 0;
}
.ubar .ut { height: 10px; border-radius: var(--r-sm); background: var(--surface-2); overflow: hidden; }
.ubar .ut i { display: block; height: 100%; border-radius: var(--r-sm); background: var(--brand); }
/* Part of a whole: the pale track is what was shown, the solid part is what
   was opened. One measure, one axis -- and a 2px surface gap so the two ends
   never read as one mark. */
.ubar .ut.pair { background: color-mix(in srgb, var(--brand) 18%, var(--surface-2)); }
.ubar .ut.pair i { border-right: 2px solid var(--surface); }
.ubar .uof { color: var(--ink-3); }
.ukey { margin: 0 0 6px; font-size: 12px; color: var(--ink-3); }
.ubar .un { font-variant-numeric: tabular-nums; font-size: 13px; color: var(--ink-2); min-width: 3ch; text-align: right; }
.ugap {
  display: inline-block; margin: 0 6px 3px 0; padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--surface-2); border: 1px solid var(--line); font-size: 12px;
}
.ugap b { font-weight: 600; color: var(--ink-2); }
.grid2cards { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* The lead worklist. The status chips carry their count, so "how much is
   waiting" is answered before anybody clicks anything. */
.enqbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; }
.enqbar .searchbox { flex: 1 1 260px; min-width: 200px; }
.enqst {
  display: inline-block; padding: 2px 9px; border-radius: var(--r-pill);
  font-size: 12px; white-space: nowrap;
  border: 1px solid var(--line); color: var(--ink-2); background: var(--surface-2);
}
.enqst.contacted { border-color: color-mix(in srgb, var(--warn) 45%, var(--line));
  color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.enqst.quoted { border-color: color-mix(in srgb, var(--ok) 45%, var(--line));
  color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.enqwork {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  margin: 16px 0 4px; padding: 14px; border-radius: var(--r-lg);
  background: var(--surface-2); border: 1px solid var(--line);
}
.enqwork .enqowner { display: flex; gap: 6px; }
.enqwork .enqowner input { flex: 1 1 auto; min-width: 0; }
.enqtouch { grid-column: 1 / -1; margin: 0; font-size: 12px; }

/* ----------------------------------------------- admin settings (mailboxes) */

.seth { margin: 0 0 4px; font-size: 15px; }
.setsub {
  margin: 20px 0 8px; font-size: 12px; font-weight: 600; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.sethelp { margin: 0 0 14px; font-size: 12.5px; color: var(--ink-2); line-height: 1.6; }
.setfoot { display: flex; align-items: center; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
.setfoot input { padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2); color: inherit; min-width: 200px; }
.linepick {
  padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); color: inherit; font-size: 13px; margin-right: 14px;
}
.corebar {
  font-size: 11.5px; padding: 3px 10px; border-radius: var(--r-pill);
  background: var(--warn-soft); color: var(--warn); white-space: nowrap;
}
.incfilter {
  display: inline-flex; align-items: center; gap: 7px; margin-bottom: 12px;
  font-size: 12.5px; color: var(--ink-2); cursor: pointer;
}
#sec-_core > summary, .dn[data-goto="sec-_core"] .dn-l { font-weight: 640; }

/* ------------------------------------------------- spreadsheet round-trip */

.sheetrep { margin-top: 16px; }
.tallies { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.tally {
  font-size: 12px; padding: 3px 10px; border-radius: var(--r-pill);
  border: 1px solid var(--line); color: var(--ink-2); background: var(--surface-2);
}
.sheettbl { margin-top: 6px; }
.sheettbl td { vertical-align: top; font-size: 12.5px; }
.sheettbl td small { display: block; color: var(--ink-3); font-size: 11px; margin-top: 1px; }
.sheettbl td:first-child { width: 1%; white-space: nowrap; }
.cellchg { margin-bottom: 2px; }
.cellchg s { color: var(--ink-3); }
.cellchg b { color: var(--ink); }
.okline { color: var(--ok); font-size: 13px; margin: 10px 0 0; }
.loginseg { display: flex; margin-bottom: 16px; }
.loginseg button { flex: 1; justify-content: center; }
.loginhelp { margin: 0 0 14px; font-size: 12.5px; color: var(--ink-2); line-height: 1.6; }
/* Advantech SSO first, the other ways in folded underneath. */
.ssobtn { margin: 4px 0 6px; }
.accbox { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); }
.accbox textarea { width: 100%; resize: vertical; }
.accquote { margin: 0 0 8px; padding-left: 10px; border-left: 3px solid var(--line); color: var(--ink-2); font-size: 12.5px; white-space: pre-wrap; }
.accreason { white-space: pre-wrap; max-width: 420px; font-size: 12.5px; }
.ssoerr { margin: 0 0 12px; }
.loginmore { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 12px; }
.loginmore > summary { cursor: pointer; font-size: 12.5px; color: var(--ink-2); list-style: revert; }
.loginmore-body { margin-top: 14px; }
.ssocb { display: inline-block; margin-top: 4px; padding: 3px 8px; border-radius: 6px;
  background: var(--surface-2); border: 1px solid var(--line); font: 12.5px/1.4 var(--mono); word-break: break-all; }
.loginfoot { display: flex; gap: 6px; margin-top: 12px; flex-wrap: wrap; }
.otpinput {
  font: 600 22px/1.2 var(--mono); letter-spacing: .3em; text-align: center;
}

.whoami { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--ink-2); }
.rolechip {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 1px 7px; color: var(--ink-3);
}
.warnpill {
  font-size: 12px; color: var(--warn); background: var(--warn-soft);
  border-radius: var(--r-pill); padding: 4px 11px;
}

/* Recipient picker: group chips you tick, plus a box for loose addresses. */
.rcpt-groups { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.rcpt-groups label {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 5px 11px; border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--surface-2); font-size: 13px;
}
.rcpt-groups input { margin: 0; }
.rcpt-gc {
  font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-3);
  border-left: 1px solid var(--line); padding-left: 7px;
}
.rcpt textarea, .grpcard textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2); color: inherit; font: inherit; resize: vertical;
}
/* The per-language link overrides. Folded away because almost every model
   wants none of them, and opened automatically for the one that does. */
.urlover { margin-top: 6px; }
.urlover > summary {
  cursor: pointer; font-size: 12px; color: var(--ink-2); list-style: none;
  padding: 3px 0;
}
.urlover > summary::-webkit-details-marker { display: none; }
.urlover > summary::before { content: "▸ "; color: var(--ink-3); }
.urlover[open] > summary::before { content: "▾ "; }
.urlover .sethelp { margin: 2px 0 8px; }

.grpcard, .catcard { border: 1px solid var(--line-soft); border-radius: var(--radius); padding: 12px 14px; }
.grphead { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.grphead .grp-name {
  flex: 1; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2); color: inherit; font-weight: 560;
}
.cathead { font-weight: 560; font-size: 13.5px; margin-bottom: 10px; }

.enqtext {
  margin: 0 0 6px; padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: var(--r-md);
  background: var(--surface-2); font: 12.5px/1.6 var(--mono); color: var(--ink);
  white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow: auto;
}

/* Table of contents down the left of the product editor. The form scrolls in
   .dlg-body; the list is sticky inside that scroll port, so it stays put while
   the fields move beside it. Every entry is type="button" - inside
   <form method="dialog"> a plain button submits the form and closes it. */
.dlgsplit {
  display: grid; grid-template-columns: 200px minmax(0, 1fr);
  gap: 26px; align-items: start;
}
.dlgtoc {
  position: sticky; top: -20px; align-self: start;
  display: flex; flex-direction: column; gap: 1px;
  padding: 20px 0; margin: -20px 0;
  background: var(--surface);
  /* Match the scroll port so a longer contents list scrolls on its own rather
     than running past the bottom of the dialog. */
  max-height: min(68vh, 640px); overflow: auto;
}
.dlgtoc h4 {
  margin: 0 0 9px 12px; font-size: 11px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}
.dlgmain { border-left: 1px solid var(--line-soft); padding-left: 26px; min-width: 0; }

.dn {
  display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left;
  padding: 6px 10px 6px 11px; border: 0; border-left: 2px solid transparent;
  border-radius: 0 var(--r-md) var(--r-md) 0; background: transparent; color: var(--ink-2);
  font-size: 13px; line-height: 1.45; cursor: pointer;
}
.dn:hover { background: var(--surface-2); color: var(--ink); }
.dn-i {
  flex: none; width: 15px; font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--ink-3); text-align: right;
}
.dn-l { flex: 1 1 auto; min-width: 0; }
.dn-n {
  flex: none; font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--ink-3); opacity: .9;
}
.dn-act {
  margin: 10px 0 0 11px; width: auto; justify-content: center;
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 5px 10px;
  font-size: 12px; color: var(--ink-2);
}
.dn-act:hover { border-color: var(--brand); }

.dlgsec-h {
  font-size: 13px; margin: 18px 0 10px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}

.attrgroup { border: 1px solid var(--line-soft); border-radius: var(--radius); margin-bottom: 12px; }
.attrgroup > summary { padding: 10px 14px; cursor: pointer; font-weight: 560; font-size: 13.5px; }
.attrgroup > div { padding: 0 14px 12px; }
.multibox { display: flex; flex-wrap: wrap; gap: 6px; }

.cardset { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); }
.cardset-q {
  width: 100%; border: 0; border-bottom: 1px solid var(--line); background: transparent;
  padding: 8px 11px; border-radius: var(--r-md) var(--r-md) 0 0;
}
.cardset-list { max-height: 260px; overflow: auto; padding: 8px 10px 10px; }
.cardset-grp { margin-bottom: 8px; }
.cardset-grp > b { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin: 4px 0 4px; }
.cardset-grp label {
  display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; padding: 2px 0; cursor: pointer;
}
.cardset-grp label code { font-size: 11.5px; flex: none; }
.cardset-grp label .cs-name { color: var(--ink-2); }
.cardset-grp label .cs-why { margin-left: auto; font-size: 11px; color: var(--bad); text-align: right; padding-left: 10px; }

.cardset-legend {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 11px; border-bottom: 1px solid var(--line); font-size: 11.5px;
}
.cs-key { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); }
.cs-key::before { content: ""; width: 8px; height: 8px; border-radius: var(--r-xs); }
.cs-tally { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cs-only { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); cursor: pointer; }

.multibox label { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; border: 1px solid var(--line); border-radius: var(--r-md); padding: 4px 9px; background: var(--surface-2); cursor: pointer; }
.multibox input { margin: 0; }
.stack { display: flex; flex-direction: column; gap: 14px; }
/* never put display:flex on a <td> - it drops the cell out of table layout */
.rowbtns { display: flex; gap: 4px; justify-content: flex-end; }
.thumb {
  width: 34px; height: 34px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: #fff;
  display: grid; place-items: center; overflow: hidden;
}
.thumb img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
/* A row of icon-only buttons. They were full-size buttons, so each row of the
   catalogue was as tall as a button with nothing but a glyph in it -- eleven
   models to a screen. Square, compact, and only coloured once you are on them,
   so a list of sixty rows is not a list of sixty red bins. */
.rowbtns .ib {
  width: 30px; height: 28px; padding: 0; display: inline-grid; place-items: center;
  font-size: 14px; line-height: 1; color: var(--ink-3); border-radius: var(--r-md);
}
.rowbtns .ib:hover { color: var(--ink); background: var(--surface-2); border-color: var(--line); }
.rowbtns .ib.danger-i:hover { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, var(--line)); }

/* The product lines a user account may work in: a short list of checkboxes,
   wrapped so a site with a dozen lines does not push the dialog wide. */
.linetick { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 6px; }

.searchbox {
  min-width: 280px; padding: 7px 11px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--surface); color: var(--ink); font: inherit;
}
.searchbox:focus { outline: 2px solid var(--brand); outline-offset: 1px; }
/* The catalogue's own search box carried its sizes inline and came out taller
   than every other control on the page. It is the same control as the others. */
.admtop { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }
.admtop .searchbox { flex: 1 1 auto; min-width: 0; }

/* ------------------------------------------- visibility and the AI importer

   Whether a product is listed is the one field in the editor with a
   consequence for a customer, so it gets a box of its own and says in a
   sentence what the three switches currently add up to. */
.visbox {
  margin-top: 14px; padding: 12px 14px; border: 1px solid var(--line);
  border-left: 3px solid var(--line); border-radius: var(--radius); background: var(--surface-2);
}
.visstate { margin: 10px 0 0; font-size: 12.5px; line-height: 1.6; }
.visbox input:disabled + span, .visbox input:disabled { opacity: .5; }

.secttl { margin: 0 0 4px; font-size: 15px; }
.warnbox {
  margin: 10px 0; padding: 10px 12px; border-radius: var(--r-md); font-size: 12.5px;
  line-height: 1.6; color: var(--warn); background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--line));
}

.aiform { display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 12px; align-items: end; }
.srccell { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.aibanner {
  margin: 0 0 18px; padding: 12px 14px; border: 1px solid var(--line);
  border-left: 3px solid var(--brand); border-radius: var(--radius); background: var(--surface-2);
}
.aibanner p { margin: 0 0 6px; font-size: 13px; line-height: 1.6; }
.aibanner .sethelp { margin: 6px 0 0; }
.ainotes { color: var(--warn); }
.aiexcerpt summary { cursor: pointer; font-size: 12.5px; color: var(--ink-2); }
.aiexcerpt pre {
  max-height: 260px; overflow: auto; font-size: 11.5px; line-height: 1.55;
  white-space: pre-wrap; background: var(--surface); padding: 10px;
  border: 1px solid var(--line); border-radius: var(--r-md); color: var(--ink-2);
}
.rochip {
  font-size: 9.5px; letter-spacing: .06em; padding: 1px 5px; margin-left: 6px;
  border-radius: var(--r-pill); vertical-align: 1px; color: var(--ink-3);
  background: var(--surface-2); border: 1px solid var(--line);
}

/* A product line's mark where it appears beside its name in the console. */
.linemark { display: inline-block; vertical-align: -3px; margin-right: 6px; }
.urlf { margin-bottom: 12px; }
.urlstate { margin: 0; min-height: 15px; font-size: 12px; line-height: 1.35; color: var(--ink-3); }
.urlstate:empty { min-height: 0; }
.urlstate.warn { color: var(--warn); }
.urlstate a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.imgprev {
  margin: 4px 0 2px; padding: 6px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2); max-width: 260px;
  display: flex; align-items: center; justify-content: center; min-height: 56px;
}
.imgprev img { max-height: 132px; max-width: 100%; object-fit: contain; display: block; }
.imgprev.loading { opacity: .45; }

/* ------------------------------------------------------- the calculation editor
   A calculation is a graph of small steps stored in the catalog. The canvas
   shows the steps and the numbers flowing between them; every number beside a
   node came back from the server, which runs the same code a visitor's request
   runs. */
.calcapp { padding: 0; overflow: hidden; }
.calcbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
}
.calcstate { font-size: 12px; font-family: var(--mono); color: var(--ink-3); }
.calcstate.warn { color: var(--warn); }

.calcsplit { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; }

.calcstage {
  position: relative; overflow: auto; background: var(--surface-2);
  background-image:
    linear-gradient(var(--line-2, var(--line)) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-2, var(--line)) 1px, transparent 1px);
  background-size: 26px 26px; touch-action: none;
}
.calcboard { position: relative; transform-origin: 0 0; }
.calcwires { position: absolute; inset: 0; overflow: visible; pointer-events: none; }

.cnode {
  position: absolute; width: 216px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md); user-select: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.cnhead {
  display: flex; align-items: flex-start; gap: 7px; padding: 7px 9px;
  border-bottom: 1px solid var(--line-2, var(--line)); cursor: grab;
}
.cnhead:active { cursor: grabbing; }
.cngrip { width: 3px; align-self: stretch; min-height: 20px; border-radius: var(--r-xs); background: var(--ink-3); }
.cnhead h4 { margin: 0; font-size: 12px; font-weight: 600; line-height: 1.3; }
.cnid { display: block; font-family: var(--mono); font-size: 10px; color: var(--ink-3); }
.cnkind {
  margin-left: auto; flex: 0 0 auto; font-size: 9.5px; color: var(--ink-3);
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 0 5px; white-space: nowrap;
}
.cnbody { padding: 6px 9px 8px; }
.cnline, .cnexpr { font-size: 11px; color: var(--ink-2); word-break: break-word; line-height: 1.5; }
.cnexpr { font-family: var(--mono); }
.cnkv { display: flex; gap: 8px; font-size: 11px; color: var(--ink-2); padding: 1px 0; }
.cnkv span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cnkv b { margin-left: auto; font-family: var(--mono); color: var(--ink); font-weight: 500; }
.cnmore { font-size: 10.5px; color: var(--ink-3); }
.cnval {
  display: flex; align-items: baseline; gap: 8px; margin-top: 6px; padding-top: 5px;
  border-top: 1px dotted var(--line);
}
.cnval span { font-size: 10.5px; color: var(--ink-3); }
.cnval b {
  margin-left: auto; font-family: var(--mono); font-size: 13px; font-weight: 600;
  color: var(--brand); font-variant-numeric: tabular-nums;
}
.cnerr { margin-top: 6px; font-size: 11px; color: var(--bad); line-height: 1.45; }

.calcside { border-left: 1px solid var(--line); overflow: auto; }
.calcside .ihead { padding: 12px 14px 10px; border-bottom: 1px solid var(--line); }
.calcside .ihead h3 { margin: 3px 0 2px; font-size: 15px; font-weight: 600; }
.calcside .isec { padding: 12px 14px; border-bottom: 1px solid var(--line); }
.calcside .isec h5 {
  margin: 10px 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3);
}
.calcside textarea { min-height: 58px; }
.calcnow { display: flex; align-items: baseline; gap: 10px; }
.calcnow span { font-size: 11.5px; color: var(--ink-3); }
.calcnow b { margin-left: auto; font-family: var(--mono); font-size: 17px; color: var(--brand); }
.calcside .trow { display: flex; align-items: center; gap: 5px; margin-bottom: 5px; }
.calcside .trow input {
  font: inherit; font-size: 11.5px; padding: 4px 6px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink);
}
.calcside .trow input.mono { font-family: var(--mono); }
.calcside .addrow {
  font: inherit; font-size: 12px; padding: 4px 10px; border-radius: var(--r-sm); width: 100%;
  border: 1px dashed var(--line); background: none; color: var(--ink-2); cursor: pointer;
}
.calcside .addrow:hover { border-color: var(--brand); color: var(--brand); }
.calcinputs { padding: 11px 14px; border-right: 1px solid var(--line); background: var(--surface-2); }
.calccases { padding: 11px 14px; background: var(--surface-2); }
.labelrow { display: flex; flex-wrap: wrap; gap: 7px; }
.labelrow .lbl { display: flex; flex-direction: column; gap: 2px; }
.labelrow .lbl span { font-size: 10.5px; color: var(--ink-3); }
.labelrow .lbl input {
  width: 92px; font: inherit; font-family: var(--mono); font-size: 11.5px; padding: 3px 6px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
}
.calccases .tcase {
  display: flex; align-items: center; gap: 9px; padding: 6px 10px; margin-bottom: 6px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  font-size: 12px; color: var(--ink-2);
}
.calccases .tcase.fail { border-color: var(--bad); }
.calccases .tcase code { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.calccases .tcase b { font-family: var(--mono); font-size: 11px; color: var(--bad); font-weight: 500; }

/* ------------------------------------------------- the question flow
   Each question carries one sentence saying when it is asked. This draws that
   sentence: a line from an option to a question is one term of it. */
.flowapp { padding: 0; overflow: hidden; }
.flowbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
}
.flowcount { font-size: 12.5px; color: var(--ink-3); }
.flowstate { font-size: 12px; font-family: var(--mono); color: var(--ink-3); }
.flowstate.warn { color: var(--warn); }

.flowstage {
  position: relative; overflow: auto; background: var(--surface-2);
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 28px 28px; touch-action: none;
}
.flowboard { position: relative; transform-origin: 0 0; }
.flowwires { position: absolute; inset: 0; overflow: visible; }
.fwire { fill: none; stroke: var(--ink-3); stroke-width: 1.6; opacity: .5; }
.fwire.hot { stroke: var(--brand); stroke-width: 2.4; opacity: 1; }
.fwire-hit { fill: none; stroke: transparent; stroke-width: 15; cursor: pointer; }

.qnode {
  position: absolute; width: 246px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-md); user-select: none;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.qhead {
  display: flex; align-items: flex-start; gap: 7px; padding: 8px 10px;
  border-bottom: 1px solid var(--line); cursor: grab;
}
.qhead:active { cursor: grabbing; }
.qgrip { width: 3px; align-self: stretch; min-height: 22px; border-radius: var(--r-xs); background: var(--ink-3); }
.qhead h4 { margin: 0; font-size: 12.5px; font-weight: 600; line-height: 1.3; }
.qkind {
  margin-left: auto; flex: 0 0 auto; font-size: 9.5px; color: var(--ink-3);
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 0 6px; white-space: nowrap;
}
.qopts { padding: 4px 0 6px; }
.qopt {
  position: relative; display: flex; align-items: center; gap: 8px;
  padding: 2.5px 12px 2.5px 11px; font-size: 11.5px; color: var(--ink-2);
}
.qopt > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qopt .ov { margin-left: auto; font-family: var(--mono); font-size: 10px; color: var(--ink-3); }
.qport {
  position: absolute; right: -7px; top: 50%; transform: translateY(-50%);
  width: 12px; height: 12px; border-radius: 50%; padding: 0;
  border: 2px solid var(--ink-3); background: var(--surface); cursor: crosshair;
}
.qport:hover, .qport.armed { border-color: var(--brand); background: var(--brand); }
.qmore { padding: 2px 11px; font-size: 10.5px; color: var(--ink-3); }
.qerr { padding: 5px 10px; font-size: 11px; color: var(--bad); border-top: 1px solid var(--line); }

.flowside { border-left: 1px solid var(--line); overflow: auto; background: var(--surface); }
.flowside .ihead { padding: 12px 14px 10px; border-bottom: 1px solid var(--line); }
.flowside .ihead h3 { margin: 3px 0 2px; font-size: 15px; font-weight: 600; line-height: 1.3; }
.flowside .isec { padding: 12px 14px; border-bottom: 1px solid var(--line); }
.flowside .isec h5 {
  margin: 0 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3);
}
.flowside .inedge {
  display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-2);
  padding: 4px 0; border-bottom: 1px dotted var(--line);
}
.flowside .inedge:last-child { border-bottom: 0; }
.flowside .inedge code { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); margin-left: auto; }
.flowside .inedge a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line); }
.flowside .inedge a:hover { color: var(--brand); border-color: var(--brand); }
.flowside .gatebox {
  font-family: var(--mono); font-size: 11px; line-height: 1.6; padding: 8px 9px;
  border-radius: var(--r-md); border: 1px solid var(--line); background: var(--surface-2);
  color: var(--ink); word-break: break-all;
}
.flowside input.mono { font-family: var(--mono); font-size: 12px; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink); }

/* ------------------------------------------------- the two canvas editors
   The calculation editor and the question flow are the same shape: a bar, a
   drawing surface between two panels, and a drawer underneath. Everything
   below is what makes that shape usable on a real screen -- it fills the
   window, it zooms, and the panels get out of the way when they are not
   being used. JS measures the top of the card and sets --tall; nothing here
   guesses at the height of a header that wraps. */
.canvasapp {
  display: flex; flex-direction: column; height: var(--tall, 620px);
  min-height: 420px; overflow: hidden;
}
.canvasapp .calcstage,
.canvasapp .flowstage { min-height: 0; }

/* The drawing scrolls; the controls over it do not. They are siblings of the
   scrolling box inside this, rather than children of it, because an absolutely
   positioned child of a scrolling element scrolls with its content -- which is
   how "適合畫面" ended up halfway down the picture. */
.canvasarea {
  position: relative; display: flex; min-width: 0; min-height: 0; overflow: hidden;
}
.canvasarea > .calcstage, .canvasarea > .flowstage { flex: 1 1 auto; min-width: 0; }
.canvasapp .calcside,
.canvasapp .flowside { min-height: 0; }

/* The zoom wrapper takes up the scaled size so the stage scrolls the right
   amount; the board inside it is scaled and keeps its own unscaled
   coordinates, which is what every stored x/y and every wire is drawn in. */
.zoomwrap { position: relative; }

/* Floating controls, bottom left of the stage, over the grid. */
.canvastools {
  position: absolute; left: 12px; bottom: 12px; z-index: 6;
  display: flex; align-items: center; gap: 2px; padding: 3px;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(6px); box-shadow: 0 2px 8px rgba(0, 0, 0, .09);
}
.canvastools button {
  font: inherit; font-size: 12px; line-height: 1; padding: 6px 9px; border: 0;
  border-radius: var(--r-sm); background: none; color: var(--ink-2); cursor: pointer; white-space: nowrap;
}
.canvastools button:hover { background: var(--surface-2); color: var(--ink); }
.canvastools .z {
  font-family: var(--mono); font-size: 11.5px; min-width: 48px; text-align: center;
  color: var(--ink-3);
}
.canvastools .sep { width: 1px; align-self: stretch; margin: 3px 3px; background: var(--line); }
.paltog {
  font: inherit; font-size: 11px; padding: 4px 6px; margin-bottom: 8px; width: 100%;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2);
  color: var(--ink-3); cursor: pointer;
}
.paltog:hover { border-color: var(--brand); color: var(--brand); }

/* The panel on the right is only worth its width while a step is selected. */
.calcside, .flowside { width: 340px; min-width: 340px; }
.sideclose {
  position: sticky; top: 0; z-index: 2; display: flex; justify-content: flex-end;
  padding: 4px 6px 0; background: var(--surface);
}
.sideclose button {
  font: inherit; font-size: 13px; line-height: 1; padding: 3px 7px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--ink-3); cursor: pointer;
}
.sideclose button:hover { background: var(--surface-2); color: var(--ink); }

/* Three name fields in a 340px panel were being cut in half. They stack. */
.calcside .grid3, .flowside .grid3 { grid-template-columns: minmax(0, 1fr); gap: 6px; }
.drawerbar {
  display: flex; align-items: center; gap: 10px; padding: 7px 14px;
  border-top: 1px solid var(--line); background: var(--surface-2);
}
.drawerbar button {
  font: inherit; font-size: 12px; padding: 3px 9px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--surface); color: var(--ink-2); cursor: pointer;
}
.drawerbar button:hover { border-color: var(--brand); color: var(--brand); }
.drawerbar .sum { font-size: 12px; color: var(--ink-3); }
.drawerbar .sum b { font-family: var(--mono); font-weight: 600; }

/* Slightly larger type on the cards themselves. At 100% they were being read
   at 11px on a 27-inch screen, which is what "too small" meant. */
.cnode { width: 226px; }
.cnhead h4 { font-size: 12.5px; }
.cnline, .cnexpr, .cnkv { font-size: 11.5px; }
.cnval b { font-size: 14px; }

/* While a tab owns the whole window the page itself must not scroll too, or
   there are two scrollbars and neither goes where you meant. */
body.noscroll { overflow: hidden; }

/* The flow's one line of instructions floats over the top-left of the stage.
   It used to sit under the board, inside the scroll, where nobody saw it. */
.hintline {
  position: absolute; right: 12px; bottom: 12px; z-index: 5; margin: 0;
  font-size: 11.5px; line-height: 1.45; color: var(--ink-3);
  padding: 5px 10px; border-radius: var(--r-md); border: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: blur(6px); max-width: min(620px, 62%); pointer-events: none;
}

.calcstage.panning, .flowstage.panning { cursor: grabbing; }
.calcstage.panning *, .flowstage.panning * { pointer-events: none; }

/* The tidy button sits in the bar, not only in the floating pill: somebody
   looking at a tangle should not have to find a 12px control to fix it. */
.calcbar .tidy, .flowbar .tidy { font-size: 12.5px; padding: 5px 11px; }

/* Controls on a card. They take no room until the pointer is over the card,
   so forty cards do not become a hundred and twenty buttons. */
.cardtools {
  display: flex; gap: 1px; margin-left: auto; align-self: flex-start;
  opacity: 0; transition: opacity .09s;
}
.cardtools:focus-within { opacity: 1; }
.cardbtn {
  font: inherit; font-size: 11px; line-height: 1; width: 19px; height: 19px;
  display: grid; place-items: center; padding: 0; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--ink-3);
}
.cardbtn:hover { border-color: var(--line); color: var(--ink); background: var(--surface); }
.cardbtn[data-card="del"]:hover { border-color: var(--bad); color: var(--bad); }

/* The option editor in the flow panel. */
.optrow {
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px 9px; margin-bottom: 7px;
  background: var(--surface-2);
}
.optrow .mv:hover { color: var(--ink); background: var(--surface); }

/* What an option means: one row per requirement, the key picked from the
   attributes table rather than typed. */
.setbox { margin-top: 7px; border-top: 1px dotted var(--line); padding-top: 7px; }
.seth {
  display: flex; align-items: center; gap: 8px; margin-bottom: 5px;
  font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
}
.setrow { display: flex; align-items: center; gap: 5px; margin-bottom: 5px; }
.setrow select, .setrow input {
  font: inherit; font-size: 11.5px; padding: 4px 6px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
}
.setrow > select[data-setkey] { flex: 1 1 58%; }
.setrow > [data-setval], .setrow > .num { flex: 1 1 42%; min-width: 0; }
.setrow select[multiple] { padding: 2px 4px; }
.setrow .num { display: flex; align-items: center; gap: 4px; }
.setrow .num input { flex: 1 1 auto; font-family: var(--mono); }
.setrow .num i { font-style: normal; font-size: 10.5px; color: var(--ink-3); white-space: nowrap; }

/* ------------------------------------------------------- the version history
   What is live, what is scheduled, and what the draft has that neither does.
   Three answers at the top, because those are the three questions somebody
   opens this page with. */
.vshead { padding: 0; overflow: hidden; }
.vsnow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.vsbox { padding: 14px 16px; border-right: 1px solid var(--line); }
.vsbox:last-child { border-right: 0; }
.vsbox h5 {
  margin: 0 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3);
}
.vsbig { margin: 0 0 3px; font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }
.vsahead { font-size: 12.5px; color: var(--warn); }
.vsbuild {
  margin: 0; padding: 8px 16px; border-top: 1px solid var(--line);
  background: var(--surface-2); font-family: var(--mono); font-size: 11px; color: var(--ink-3);
}

.vstable td { vertical-align: top; }
.vsn { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2); white-space: nowrap; }
.vspin {
  display: inline-block; font-family: var(--sans, inherit); font-size: 10px;
  padding: 1px 6px; border-radius: var(--r-pill); border: 1px solid var(--line); color: var(--ink-3);
}
.vstitle { font-size: 13px; font-weight: 560; line-height: 1.35; }
.vstag {
  display: inline-block; margin-top: 5px; font-size: 11px;
  padding: 1px 8px; border-radius: var(--r-pill); border: 1px solid var(--line);
}
.vstag.soon { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.vsacts { display: flex; flex-wrap: wrap; gap: 4px; }

.vsdiff { margin-top: 9px; padding-top: 8px; border-top: 1px dotted var(--line); }
.vschanges { display: flex; flex-wrap: wrap; gap: 5px; }
.vschg {
  font-size: 11px; padding: 2px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2);
}
.vschg i { font-style: normal; font-weight: 600; margin-right: 5px; }
.vschg.removed { border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.vschg.removed i { color: var(--bad); }

/* The assistant conversation, as a salesperson reads it on the enquiry. */
.enqchat { display: grid; gap: 7px; margin: 4px 0 0; }
.enqchat div {
  font-size: 12.5px; line-height: 1.55; padding: 8px 11px; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--surface-2);
}
.enqchat b {
  display: block; font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 3px; font-weight: 600;
}

/* The console assistant reuses the selector's panel; only what is different
   is set here. */
.cassist .asstrefused {
  margin-top: 6px !important; font-size: 11.5px !important; color: var(--warn) !important;
  line-height: 1.5;
}

/* ------------------------------------------------------------ diagnostics

   A page of numbers, so: tabular figures, a monospace column for anything
   that is really a string the machine chose, and the long text in a box that
   scrolls rather than pushing the page apart. */

.dbgstats { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.dbgstat {
  flex: 1 1 130px; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--surface-2);
}
.dbgstat .k { display: block; font-size: 11.5px; color: var(--ink-3); }
.dbgstat b { font-size: 17px; font-variant-numeric: tabular-nums; }
.dbgh { margin: 16px 0 6px; font-size: 12.5px; color: var(--ink-2); font-weight: 650; }
.dbgpre {
  margin: 0; padding: 12px 14px; max-height: 320px; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md);
  font-family: var(--mono); font-size: 11.5px; line-height: 1.6; color: var(--ink-2);
  white-space: pre-wrap; word-break: break-word;
}
tr.bad td { background: color-mix(in srgb, var(--bad) 7%, transparent); }

.dbgrow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.dbgdet { margin-top: 12px; }
.dbgdet summary { cursor: pointer; font-size: 12.5px; color: var(--ink-2); }
.dbgdet[open] summary { margin-bottom: 8px; }
.mailframe {
  width: 100%; height: 420px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: #fff;
}
.mailrow { border: 1px solid var(--line); border-radius: var(--r-md); margin-top: 8px; overflow: hidden; }
.mailrow.bad { border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); }
.mailhead {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 12px;
  background: none; border: 0; font: inherit; color: var(--ink); cursor: pointer; text-align: left;
}
.mailhead:hover { background: var(--surface-2); }
.mailbody { padding: 0 12px 12px; }

/* One bar, the whole spend. Colour says what the segment bought, width says
   how much of the bill it was -- which is the only comparison anybody makes
   when they open this. */
.wastebar {
  display: flex; height: 12px; margin-top: 14px; overflow: hidden;
  border-radius: 99px; background: var(--line-soft);
}
.wastebar span { min-width: 2px; transition: width var(--t-slow, .3s) var(--e-out, ease); }
.wastebar .w-ok { background: var(--ok); }
.wastebar .w-warn { background: var(--warn); }
.wastebar .w-bad { background: var(--bad); }
.dbgstat.warn { border-color: color-mix(in srgb, var(--warn) 55%, var(--line)); }
.dbgstat b small { font-size: 12px; font-weight: 500; color: var(--ink-3); }

/* The mail relay link.
   Two states and a box for a secret that is shown once. The chip modifiers
   below are also what the diagnostics page's timings have always asked for. */
.relok { color: var(--ok); }
.relbad { color: var(--bad); }
.chip.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); background: var(--warn-soft); }
.chip.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, var(--line)); background: var(--bad-soft); }
.keybox {
  margin: 12px 0 0; padding: 12px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--ok) 45%, var(--line));
  background: var(--ok-soft);
}
.keybox .dbgpre { margin: 0; }

/* Passkeys: the device list in the account's own dialog. */
.pkname {
  width: 60%; min-width: 140px; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
}
.pkname + .chip { margin-left: 8px; }

/* The welcome card a new account meets once: the same three-step shape the
   public page's introduction uses, so the two read as one product. */
.welcome::backdrop { background: color-mix(in srgb, var(--ink) 42%, transparent); }
.welcome-steps { display: grid; gap: 12px; margin: 14px 0 4px; }
.welcome-step { display: flex; gap: 12px; align-items: flex-start; }
.welcome-step .n {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; font-size: 12.5px; font-weight: 700;
  background: var(--brand); color: #fff;
}
.welcome-step h3 { margin: 2px 0 3px; font-size: 14px; }
.welcome-step p { margin: 0; font-size: 13px; line-height: 1.6; color: var(--ink-2); }

/* ---------------------------------------------- simpler question & calc editors
   A list in the order customers see as the default view of the questions, a
   side panel that goes step by step, conditions built from dropdowns, and the
   model a button away wherever typing three languages or a formula was the
   hard part. */
.vseg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.vseg .tbtn { border: 0; border-radius: 0; margin: 0; }
.vseg .tbtn + .tbtn { border-left: 1px solid var(--line); }
.vseg .tbtn[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand); }

.flowlist { overflow: auto; min-height: 0; padding: 12px 14px 24px; }
.flhelp { margin: 0 0 10px; font-size: 12.5px; color: var(--ink-3); }
.flrow {
  display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px; margin-bottom: 6px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  cursor: pointer; transition: border-color .12s, box-shadow .12s;
}
.flrow:hover { border-color: color-mix(in srgb, var(--brand) 45%, var(--line)); }
.flrow:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.flrow.sel { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft); }
.flrow.off { opacity: .6; }
.flrow.bad { border-color: var(--bad); }
.flnum {
  flex: 0 0 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-2); color: var(--ink-2); font-size: 12px; font-variant-numeric: tabular-nums;
}
.flmain { flex: 1 1 auto; min-width: 0; }
.fltitle { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 14px; line-height: 1.4; }
.fltitle .qkind { margin-left: 0; }
.flwhen { margin-top: 3px; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.flwhen.always { color: var(--brand); }
.flrow .qerr { border: 0; padding: 4px 0 0; }
.flopts { flex: 0 0 auto; font-size: 12px; color: var(--ink-3); white-space: nowrap; padding-top: 4px; }
.flmv { display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto; }
.flmv .mv {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-3);
  border-radius: var(--r-sm); font: inherit; font-size: 11px; line-height: 1; padding: 3px 6px; cursor: pointer;
}
.flmv .mv:hover:not(:disabled) { color: var(--brand); border-color: var(--brand); }
.flmv .mv:disabled { opacity: .35; cursor: default; }
.listview .flowside { width: 420px; min-width: 420px; }
@media (max-width: 1250px) { .listview .flowside { width: 360px; min-width: 360px; } }
@media (max-width: 760px) {
  .listview .flowsplit { grid-template-columns: minmax(0, 1fr); }
  .listview .flowside { width: auto; min-width: 0; border-left: 0; border-top: 1px solid var(--line); }
  .listview .flowsplit:not(.noside) .flowlist { display: none; }
}

/* The inspector as numbered steps. */
.flowside .isec.step h5, .calcside .field.i18nf > span {
  display: flex; align-items: center; gap: 8px;
}
.flowside .isec.step h5 { text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--ink); }
.flowside .isec.step h5 i {
  font-style: normal; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
  background: var(--brand); color: #fff; font-size: 11px; flex: 0 0 auto;
}
.flowside .isec.step h5 .aibtn, .calcside .i18nf > span .aibtn,
.calcside .field > span .aibtn { margin-left: auto; }
.lsub { font-size: 11.5px; color: var(--ink-3); margin: 8px 0 4px; }
.lsub .muted { font-size: 11px; }
.lrows { display: grid; gap: 4px; }
.lrow { display: flex; align-items: center; gap: 6px; margin: 0; }
.lrow input, .olangs input, .edgeadd select, .caseval input {
  font: inherit; font-size: 12.5px; padding: 5px 7px; min-width: 0; flex: 1 1 auto;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink);
}
.lg {
  flex: 0 0 26px; font-size: 10px; font-weight: 600; color: var(--ink-3); text-align: center;
  letter-spacing: .04em;
}
.flags { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; }
.flags .field { margin: 0; }
.flowside details.adv > summary, .calcside details.adv > summary {
  cursor: pointer; font-size: 12px; color: var(--ink-3);
}
.flowside details.adv[open] > summary, .calcside details.adv[open] > summary { margin-bottom: 8px; }

.optrow .top input[data-olabel] { font-family: inherit; font-size: 13px; }
.optrow .onum { font-size: 11px; color: var(--ink-3); width: 14px; text-align: right; flex: 0 0 auto; }
.olangs { display: grid; gap: 4px; margin-top: 6px; padding-left: 20px; }
.olangs label { display: flex; align-items: center; gap: 6px; margin: 0; }
.olangs input { font-size: 12px; padding: 4px 6px; background: var(--surface); }
.olangs .oval input { font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); }
.olangs .oval .lg { font-weight: 500; }
details.setbox { margin: 7px 0 0 20px; }
details.setbox > summary { cursor: pointer; list-style: revert; margin-bottom: 0; }
details.setbox[open] > summary { margin-bottom: 6px; }
details.setbox > summary .muted { text-transform: none; letter-spacing: 0; font-size: 11px; }
.setsay { margin-bottom: 6px; }

.aibtn {
  display: inline-flex; align-items: center; gap: 4px; font: inherit; font-size: 11.5px; font-weight: 500;
  text-transform: none; letter-spacing: 0; line-height: 1.2;
  padding: 3px 9px; border-radius: var(--r-pill); cursor: pointer; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--brand) 45%, var(--line));
  background: var(--brand-soft); color: var(--brand);
}
.aibtn:hover:not(:disabled) { border-color: var(--brand); }
.aibtn:disabled { opacity: .6; cursor: progress; }

.edgeadd { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.edgeadd select { flex: 1 1 120px; }
.edgeadd .btn { padding: 5px 10px; font-size: 12px; }
.flowside .inedge > span { flex: 1 1 auto; }

/* The condition builder. */
.cb { display: grid; gap: 6px; }
.cb-group {
  display: grid; gap: 5px; padding: 8px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface-2);
}
.cb-row { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.cb-row select, .cb-row input {
  font: inherit; font-size: 12px; padding: 4px 6px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
}
.cb-row .cb-l { flex: 1 1 130px; }
.cb-row .cb-op { flex: 0 1 auto; }
.cb-row .cb-v { flex: 1 1 100px; }
.cb-row .x { border: 0; background: none; color: var(--ink-3); cursor: pointer; font: inherit; padding: 0 3px; }
.cb-row .x:hover { color: var(--bad); }
.cb-join { font-size: 11.5px; color: var(--ink-3); min-width: 30px; }
.cb-or { font-size: 11.5px; font-weight: 600; color: var(--brand); text-align: center; }
.cb-add {
  justify-self: start; font: inherit; font-size: 11.5px; padding: 3px 9px; cursor: pointer;
  border: 1px dashed var(--line); border-radius: var(--r-sm); background: none; color: var(--ink-2);
}
.cb-add:hover { border-color: var(--brand); color: var(--brand); }
.cb-empty { margin: 0; font-size: 12px; color: var(--ink-3); }
.cb-say {
  margin: 2px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-2);
  padding: 6px 8px; border-left: 2px solid var(--brand); background: var(--surface-2);
}
.cb-adv > summary { cursor: pointer; font-size: 11.5px; color: var(--ink-3); }
.cb-adv .cb-text {
  width: 100%; margin-top: 6px; font-family: var(--mono); font-size: 12px; padding: 5px 7px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink);
}
.cb-rawnote { margin: 0; font-size: 12px; }

/* The guided new question. */
.nqdlg .dlg-body { display: grid; gap: 14px; }
.nq-step { display: flex; gap: 12px; }
.nq-n {
  flex: 0 0 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--brand); color: #fff; font-size: 13px; font-weight: 600;
}
.nq-b { flex: 1 1 auto; min-width: 0; display: grid; gap: 6px; }
.nq-b > b, .nq-b > label > b { font-size: 14px; }
.nq-b input, .nq-b textarea, .askdlg textarea, .askdlg input {
  font: inherit; font-size: 14px; padding: 8px 10px; width: 100%;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); color: var(--ink);
}
.nq-b .sethelp { margin: 0; }
.nq-kinds { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 6px; }
.nq-kind {
  display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
}
.nq-kind:has(input:checked) { border-color: var(--brand); background: var(--brand-soft); }
.nq-kind input { width: auto; margin-top: 3px; }
.nq-kind span { display: grid; gap: 2px; font-size: 13px; }
.nq-kind i { font-style: normal; font-size: 12px; color: var(--ink-3); }
.nq-b .field.row { margin: 0; }
.nq-b .field.row input { width: auto; }
.nq-after { margin-left: 24px; }
.nq-after select { font-size: 13px; }
.nq-adv > summary { cursor: pointer; font-size: 12.5px; color: var(--ink-3); }
.askdlg { max-width: 560px; width: calc(100vw - 32px); }

/* The calculation panel. */
.kindwhat { margin: 0; padding: 8px 14px; font-size: 12px; line-height: 1.5; color: var(--ink-2); border-bottom: 1px solid var(--line); background: var(--surface-2); }
.calcside .field > span { display: flex; align-items: center; gap: 6px; }
.calcside .chips.ops .chip { font-size: 11px; }
.casebox {
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px; margin-bottom: 7px;
  display: grid; gap: 6px; background: var(--surface);
}
.casebox.last { background: var(--surface-2); }
.casehead { display: flex; align-items: center; font-size: 12px; }
.casehead .x { margin-left: auto; border: 0; background: none; color: var(--ink-3); cursor: pointer; font: inherit; }
.casehead .x:hover { color: var(--bad); }
.caseval { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; color: var(--ink-2); }
.caseval span { white-space: nowrap; }

/* The product line's icon, picked rather than typed. */
.iconpick { display: grid; grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: 6px; }
.ipick {
  display: grid; justify-items: center; gap: 3px; padding: 7px 4px 6px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
  color: var(--ink-2); font: inherit; font-size: 11px;
}
.ipick svg.art-line { width: 30px; height: 28px; display: block; color: var(--brand); }
.ipick svg.art-line .a-fill { fill: currentColor; }
.ipick svg.art-line .a-stroke { stroke: currentColor; }
.ipick svg.art-line .a-bg-dot { fill: var(--surface-2); }
.ipick .inone { height: 28px; display: grid; place-items: center; font-size: 18px; color: var(--ink-3); }
.ipick:hover { border-color: color-mix(in srgb, var(--brand) 50%, var(--line)); }
.ipick[aria-checked="true"] { border-color: var(--brand); background: var(--brand-soft); color: var(--ink); box-shadow: 0 0 0 1px var(--brand); }
.iconown { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 12px; color: var(--ink-3); }
.iconown input { width: 56px; text-align: center; font-size: 16px; padding: 4px; }
.linepub { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; flex-wrap: wrap; }
.linepub span { flex: 1 1 300px; }
.field .iconown { white-space: nowrap; }
.field .iconown input { width: 56px; flex: 0 0 56px; }

/* Visitors. */
.vflags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin: 0 0 12px; }
.vflags .field { margin: 0; }
.vdays {
  display: flex; align-items: flex-end; gap: 2px; height: 80px; margin-top: 14px;
  padding: 0 2px; border-bottom: 1px solid var(--line);
}
.vdays span { flex: 1 1 0; min-width: 2px; background: var(--brand); border-radius: 2px 2px 0 0; opacity: .85; }
.vdays span:hover { opacity: 1; }
.vdaysx { display: flex; justify-content: space-between; font-size: 11px; color: var(--ink-3); margin-top: 3px; }
.vgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 900px) { .vgrid { grid-template-columns: minmax(0, 1fr); } }
.vpick { cursor: pointer; border-radius: var(--r-sm); }
.vpick:hover { background: var(--surface-2); }
.vlist tr.open > td { background: var(--brand-soft); }
.vlist tr.vtl > td { background: var(--surface-2); padding: 12px 14px; }
.vbox { display: grid; gap: 10px; }
.vfacts { margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--ink-2); display: grid; gap: 2px; word-break: break-all; }
.vsteps { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; font-size: 13px; }
.vsteps li { display: grid; grid-template-columns: 56px 22px minmax(0, 1fr); align-items: baseline; }
.vsteps .vt { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); text-align: right; padding-right: 8px; }
.vsteps .vk { text-align: center; color: var(--brand); }
.vfoot { display: flex; align-items: center; gap: 10px; }
.vfoot .btn { margin-left: auto; }

/* Insights. */
.funnel { display: grid; gap: 6px; }
.fstep { position: relative; min-height: 34px; border-radius: var(--r-md); background: var(--surface-2); overflow: hidden; }
.fstep .fbar { position: absolute; inset: 0 auto 0 0; background: color-mix(in srgb, var(--brand) 22%, transparent); border-right: 2px solid var(--brand); }
.fstep .flab { position: relative; display: flex; align-items: center; gap: 12px; padding: 7px 12px; font-size: 13px; }
.fstep .flab span { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.fstep .fdrop { margin-left: auto; font-size: 12px; color: var(--warn) !important; }
.fstep .fdrop.bad { color: var(--bad) !important; font-weight: 600; }
.grid tr.warnrow > td { background: var(--warn-soft); }
.qbar { display: inline-block; width: 48px; height: 7px; border-radius: 4px; background: var(--surface-2); vertical-align: middle; overflow: hidden; }
.qbar i { display: block; height: 100%; background: var(--bad); }
b.good { color: var(--ok); }
.insc .grid { font-size: 13px; }

/* Holiday styles card. */
.festwrap { margin-top: 12px; overflow-x: auto; }
.festtable td { vertical-align: middle; }
.festico { display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  margin-right: 8px; vertical-align: middle; }
.festico svg { width: 17px; height: 17px; }
.chip.festnow { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.festtable tr.festoff td { opacity: .55; }
.festtable tr.festoff td:first-child, .festtable tr.festoff td:last-child { opacity: 1; }
.chip.festwarn { color: var(--warn); border-color: var(--warn); background: var(--warn-soft); }
.festfoot { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.festdlg { width: min(860px, calc(100vw - 32px)); }
.festdlg .festdemo { margin: 0 0 14px; }
.festdlg .setsub { margin: 16px 0 6px; }
.festpickart { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); }
.festpickart .ipick svg { width: 26px; height: 26px; }
.festdates { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.festdates .linkish { margin-left: 2px; }
.festaddday { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.festnext { margin: 2px 0 0; font-size: 13px; color: var(--ink-2); }
.festnext .warn { color: var(--warn); font-weight: 600; }
@media (max-width: 640px) { .festdlg .grid3 { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- manual
   The 說明文件 page (docs.js): contents on the left, the text on the right,
   one column on a phone. Set for reading: a measure of about 80 characters,
   generous line height, and the console's own colours. */
.docbtn.on { color: var(--brand); border-color: var(--brand); }
.docs { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 24px; align-items: start; }
.docs > * { min-width: 0; }
.docbody { overflow-wrap: anywhere; }
.docnav {
  position: sticky; top: 78px; max-height: calc(100vh - 92px); overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px; font-size: 13px;
}
.docnav input[type="search"] { width: 100%; box-sizing: border-box; padding: 7px 10px; font: inherit;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); color: var(--ink); }
.docnav-count { margin: 6px 2px 0; color: var(--ink-2); min-height: 1em; }
.doctoc, .doctoc ol { list-style: none; margin: 0; padding: 0; }
.doctoc > li { margin-top: 10px; }
.doctoc > li > a { font-weight: 600; color: var(--ink); }
.doctoc ol { margin: 4px 0 0 10px; border-left: 1px solid var(--line-soft); }
.doctoc ol a { display: block; padding: 3px 0 3px 10px; color: var(--ink-2); }
.doctoc a { text-decoration: none; border-radius: var(--r-sm); }
.doctoc a:hover { color: var(--brand); }
.doctoc a.on { color: var(--brand); font-weight: 600; }
.doctoc li[hidden] { display: none; }
.docnav-foot { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.docbody {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 32px 32px; max-width: 900px; line-height: 1.75; font-size: 14.5px; color: var(--ink);
}
.docbody [hidden] { display: none !important; }
.docbody h2 { font-size: 22px; margin: 34px 0 10px; padding-top: 18px; border-top: 1px solid var(--line); scroll-margin-top: 84px; }
.docbody .docchap:first-child h2 { border-top: 0; }
.docbody h3 { font-size: 17px; margin: 28px 0 8px; scroll-margin-top: 84px; }
.docbody h4 { font-size: 14.5px; margin: 20px 0 6px; color: var(--ink-2); }
.docbody p { margin: 8px 0; }
.docbody ul, .docbody ol { margin: 8px 0; padding-left: 22px; }
.docbody li { margin: 3px 0; }
.docbody code { font-size: 12.5px; background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: var(--r-xs); padding: 1px 5px; }
.docbody a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.doccode { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px 14px; overflow: auto; font-size: 12.5px; line-height: 1.55; }
.doccode code { background: none; border: 0; padding: 0; }
.doctable { overflow-x: auto; margin: 10px 0; }
.doctable table { border-collapse: collapse; width: 100%; font-size: 13.5px; line-height: 1.55; }
.doctable th, .doctable td { border: 1px solid var(--line); padding: 6px 10px; text-align: left; vertical-align: top; }
.doctable th { background: var(--surface-2); font-weight: 600; }
.docnote { display: flex; gap: 10px; margin: 12px 0; padding: 10px 14px; border-radius: var(--r-md);
  background: var(--brand-soft); border-left: 3px solid var(--brand); }
.docnote.warn { background: var(--warn-soft); border-left-color: var(--warn); }
.docnote p { margin: 0; }
.docnote-i { flex: none; font-weight: 700; color: var(--brand); }
.docnote.warn .docnote-i { color: var(--warn); }
mark.dochit { background: #ffe58a; color: inherit; border-radius: 2px; padding: 0 1px; }
.docflash { animation: docflash 1.4s ease; }
@keyframes docflash { 0%, 40% { background: color-mix(in srgb, var(--brand) 18%, transparent); } 100% { background: transparent; } }
.docempty { color: var(--ink-2); padding: 20px 0; }
@media (max-width: 900px) {
  .docs { grid-template-columns: minmax(0, 1fr); }
  .docnav { position: static; max-height: 40vh; }
  .docbody { padding: 4px 16px 24px; }
}
@media print {
  .docnav, .tabs, .topbar, .tourfab, .asstfab { display: none !important; }
  .docs { display: block; }
  .docbody { border: 0; padding: 0; max-width: none; font-size: 11pt; }
  .docbody h2 { break-before: page; border-top: 0; }
  .docbody .docchap:first-child h2 { break-before: auto; }
  .docnote, .doctable tr, .doccode { break-inside: avoid; }
}
.festbusy { opacity: .6; pointer-events: none; }

/* Invitations (invites.js). */
.invdlg { width: min(900px, calc(100vw - 32px)); }
.invbatch { border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; background: var(--surface-2); }
.invrow { border: 1px solid var(--line-soft); border-radius: var(--r-md); padding: 8px 10px; margin: 6px 0; }
.invrow-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.invrow-head .linkish { margin-left: auto; }
.inv-role { font: inherit; padding: 4px 6px; margin-bottom: 6px; }
.inv-ticks { margin: 2px 0 4px; }
.okbox { border: 1px solid color-mix(in srgb, var(--ok) 40%, var(--line)); background: var(--ok-soft); border-radius: var(--r-md); padding: 10px 12px; }
.chip.inv-accepted { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.chip.inv-pending { color: var(--brand); border-color: var(--brand); }
.chip.inv-expired, .chip.inv-revoked, .chip.inv-closed { color: var(--ink-3); }

/* Feedback tracker (tickets.js). */
.tkbtn { position: relative; }
.tkbtn[data-unread]:not([data-unread=""])::after {
  content: attr(data-unread); position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--bad); color: #fff; font-size: 11px; line-height: 18px; text-align: center; font-weight: 700;
}
.tkfilters { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin: 12px 0 0; }
.tkfilter { border: 1px solid var(--line); background: var(--surface); color: var(--ink-2); border-radius: 999px; padding: 4px 11px; font: inherit; font-size: 13px; cursor: pointer; }
.tkfilter b { color: var(--ink); margin-left: 2px; }
.tkfilter.on { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }
.tkq { flex: 1; min-width: 180px; max-width: 320px; padding: 6px 10px; font: inherit; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); color: var(--ink); }
.tktable { margin-top: 12px; }
.tkdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--bad); margin-right: 6px; vertical-align: middle; }
.chip.tk-new { color: var(--brand); border-color: var(--brand); }
.chip.tk-in_progress { color: var(--warn); border-color: var(--warn); background: var(--warn-soft); }
.chip.tk-need_info { color: #7a4fb5; border-color: #7a4fb5; }
.chip.tk-done { color: var(--ok); border-color: var(--ok); background: var(--ok-soft); }
.chip.tk-rejected { color: var(--bad); border-color: var(--bad); background: var(--bad-soft); }
.tktext { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.65; }
.tkbody { background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: var(--r-md); padding: 12px 14px; }
.tkctx { font-size: 12px; margin: 6px 0 0; }
.tkpics { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.tkpics img { max-width: 220px; max-height: 160px; border: 1px solid var(--line); border-radius: var(--r-sm); display: block; object-fit: cover; }
.tkevents { list-style: none; padding: 0; margin: 0; border-left: 2px solid var(--line); }
.tkev { margin: 0 0 14px; padding-left: 14px; position: relative; }
.tkev::before { content: ""; position: absolute; left: -6px; top: 6px; width: 10px; height: 10px; border-radius: 50%; background: var(--line); }
.tkev-status::before { background: var(--brand); }
.tkev-head { font-size: 13px; margin-bottom: 4px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.tkmove { display: inline-flex; gap: 4px; align-items: center; }
.tkreply { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
.tkpicrow { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; font-size: 12.5px; }
.tkstrip { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.tkthumb { position: relative; }
.tkthumb img { width: 96px; height: 72px; object-fit: cover; border-radius: var(--r-sm); border: 1px solid var(--line); display: block; }
.tkthumb button { position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; border-radius: 50%; border: 0; background: var(--ink); color: var(--surface); cursor: pointer; line-height: 20px; padding: 0; }
.tkdecide { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; font-size: 13px; color: var(--ink-2); }
.tk-to-done { color: var(--ok); border-color: var(--ok); }
.tk-to-rejected { color: var(--bad); border-color: var(--bad); }
.tk-to-in_progress { color: var(--warn); border-color: var(--warn); }
.tkdlg { width: min(720px, calc(100vw - 32px)); }
.tktitle { font-size: 20px; margin: 12px 0 6px; line-height: 1.35; overflow-wrap: anywhere; }
.chip.tkpub { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 50%, var(--line)); background: var(--ok-soft); }
.chip.tkseen { color: var(--ok); border-color: var(--ok); }
.tkpubbox { margin: 8px 0; padding: 8px 12px; border-left: 3px solid var(--ok); background: var(--ok-soft); border-radius: var(--r-sm); font-size: 13.5px; }

/* Link check (links.js) */
.lk-banner { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; padding: 8px 12px;
  border: 1px solid color-mix(in srgb, var(--bad) 40%, var(--line)); background: var(--bad-soft);
  color: var(--bad); border-radius: var(--r-md); font-size: 13px; }
.lk-banner .btn { margin-left: auto; }
.lk-mark { margin-left: 6px; }
.lk-sum { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.lk-run { margin: 4px 0 0; color: var(--ink-2); }
.lk-grid td { vertical-align: top; }
.lk-name { font-size: 12px; max-width: 220px; }
.lk-url { font-size: 11.5px; max-width: 420px; overflow-wrap: anywhere; margin-top: 2px; }
.lk-url a { color: var(--ink-3); }
.lk-why { font-size: 12px; margin-top: 4px; max-width: 260px; }
.lk-why.bad { color: var(--bad); }
.lk-why.warn { color: var(--warn); }
.lk-set summary { cursor: pointer; }
.lk-set { margin-top: 14px; }
.lk-psm { margin: 4px 0 10px; padding-left: 18px; font-size: 13px; line-height: 1.7; }
.lk-sws { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 10px; margin: 12px 0 4px; }
.lk-sw { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--surface-2); cursor: pointer; }
.lk-sw input { margin-top: 3px; width: 18px; height: 18px; flex: none; }
.lk-sw-t { display: flex; flex-direction: column; gap: 2px; font-size: 13px; line-height: 1.45; }

/* Solutions offer their product line's products (lineDialog). */
.lprods { max-height: 260px; overflow: auto; border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 6px 10px; background: var(--surface-2); }
.lprod { display: flex; gap: 8px; align-items: baseline; padding: 3px 0; font-size: 13px; cursor: pointer; }
.lprod code { flex: none; }
.uscope + .uscope { margin-top: 4px; }
.chip.pl { border-style: dashed; }

/* An open access request: a dot on the menu that holds 使用者. */
.accdot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--warn); margin-left: 4px; vertical-align: middle; }

/* Viewing as somebody else: impossible to miss, and the way back is on it. */
.viewas-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; padding: 10px 14px;
  border-radius: var(--radius); background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line)); font-size: 13.5px;
}
.viewas-ro { color: var(--ink-2); font-size: 12.5px; }
.viewer-bar {
  margin: 0 0 12px; padding: 8px 14px; border-radius: var(--radius); font-size: 13px;
  background: var(--brand-soft); border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line));
  color: var(--ink-2);
}
.viewas-list { display: grid; gap: 6px; margin: 4px 0 14px; }
.viewas-pick {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; text-align: left; padding: 9px 12px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); cursor: pointer;
}
.viewas-pick:hover { border-color: var(--brand); background: var(--brand-soft); }
.viewas-pick small { flex-basis: 100%; color: var(--ink-3); font-size: 12px; }

/* Where each category's mail goes: one row each. */
.catbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 10px; }
.catbar input[type="search"] { max-width: 280px; }
.cattbl td { vertical-align: middle; }
.catmails { font-size: 12.5px; color: var(--ink-2); word-break: break-all; }
/* The current page's name beside its menu is a nicety; on a narrow screen
   the row is worth more. */
@media (max-width: 960px) { .tabgroup .tabbtn .gnow { display: none; } }

/* A chip that opens something. */
.chiplink { cursor: pointer; font: inherit; font-size: 12px; }
.chiplink:hover { border-color: var(--brand); color: var(--brand); }

/* Settings: a rule between two halves of one card, and a warning line. */
.sethr { border: 0; border-top: 1px solid var(--line); margin: 16px 0 14px; }
.sethelp.warn { color: var(--warn); }

/* An enquiry's configurator builds. */
.enqbuild { margin: 6px 0 10px; padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--radius); }
.enqbuild ul { margin: 6px 0 0; padding-left: 18px; font-size: 13px; }
.enqbuild .chip { margin-left: 6px; }

/* The order of a product line's filter bar (fields page). */
.fo-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; max-width: 640px; }
.fo-list li {
  display: flex; align-items: center; gap: 10px; padding: 4px 6px 4px 10px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.fo-n { width: 20px; color: var(--ink-3); font-variant-numeric: tabular-nums; font-size: 12px; }
.fo-l { flex: 1; min-width: 0; font-weight: 560; }
.fo-list code { font-size: 11.5px; color: var(--ink-3); }

/* A phone. The console is built for a desk, but the numbers get checked on the
   way to a meeting: the forms stack, the counters go two by two, and a wide
   table scrolls inside its card instead of dragging the page sideways (which
   also left the header at the old width, half across the screen). */
@media (max-width: 640px) {
  .grid2cards, .grid3, .aiform, .enqwork, .dlgsplit { grid-template-columns: minmax(0, 1fr); }
  .utiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .utile strong { font-size: 22px; }
  .uhead { flex-wrap: wrap; }
  .ubar { grid-template-columns: minmax(90px, 1fr) minmax(60px, 1.4fr) auto; }
  .card > table.grid, .card > .tablewrap { display: block; max-width: 100%; overflow-x: auto; }
  .aiform .btn { justify-self: start; }
}
