/* ═══════════════════════════════════════════════════════════════════════
   Dialectic Layer mockup — additions on top of adastra.css.

   adastra.css is the shared house format and is never edited. Everything
   here is a block that format does not carry: the explorer split, the
   confidence scale, the trace panel, the code blocks and the two charts.
   Same tokens, same radii, same borders, so it reads as one system.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Explorer split: object list beside a detail pane ─────────────────── */
.split {
  display: grid;
  grid-template-columns: 17rem 1fr;
  gap: 1.25rem;
  align-items: start;
}
.split-wide { grid-template-columns: 1fr 21rem; }

.objlist { padding: 0.5rem; }
.objlist-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 0.5rem 0.7rem;
  cursor: pointer;
  color: var(--c-text);
  font-size: 0.9rem;
  transition: background 0.15s, border-color 0.15s;
}
.objlist-item:hover { background: var(--c-panel2); }
.objlist-item.active {
  background: rgba(22, 59, 110, 0.07);
  border-color: var(--c-chip-border);
  color: var(--c-heading);
  font-weight: 700;
}
.objlist-item .objlist-meta {
  display: block;
  color: var(--c-dim);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.04em;
}

/* ─── Confidence scale ─────────────────────────────────────────────────── */
.conf {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.conf-bar {
  width: 3.2rem;
  height: 6px;
  border-radius: 999px;
  background: var(--c-bg2);
  overflow: hidden;
}
.conf-bar > span { display: block; height: 100%; border-radius: 999px; }
.conf.high  { color: #3E8A54; }
.conf.high  .conf-bar > span { background: var(--c-green); }
.conf.mid   { color: var(--c-gold); }
.conf.mid   .conf-bar > span { background: var(--c-gold); }
.conf.low   { color: var(--c-danger); }
.conf.low   .conf-bar > span { background: var(--c-danger); }

/* ─── Key and value rows, for specs and definitions ────────────────────── */
.kv { display: grid; grid-template-columns: 11rem 1fr; gap: 0.45rem 1rem; }
.kv dt {
  color: var(--c-muted);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding-top: 0.15rem;
}
.kv dd { color: var(--c-text); font-size: 0.9rem; }

/* ─── Code, for generated queries and specs ────────────────────────────── */
.mono {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1.55;
  background: #F4F4F1;
  border: 1px solid var(--c-line);
  border-radius: 8px;
  padding: 0.75rem 0.9rem;
  color: #2A2A2A;
  white-space: pre;
  overflow-x: auto;
}
code.inl {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.84em;
  background: #F4F4F1;
  border: 1px solid var(--c-line);
  border-radius: 5px;
  padding: 0.05rem 0.3rem;
  color: #2A2A2A;
}

/* ─── Trace panel ──────────────────────────────────────────────────────── */
.trace-step {
  display: grid;
  grid-template-columns: 1.4rem 1fr auto;
  gap: 0.6rem;
  align-items: start;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--c-line);
  font-size: 0.85rem;
}
.trace-step:last-child { border-bottom: none; }
.trace-num {
  width: 1.4rem; height: 1.4rem;
  border-radius: 999px;
  background: rgba(22, 59, 110, 0.10);
  color: var(--c-heading);
  font-size: 0.7rem;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.trace-tool { color: var(--c-heading); font-weight: 700; }
.trace-note { color: var(--c-muted); font-size: 0.8rem; }
.trace-ms {
  color: var(--c-dim);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ─── Callouts ─────────────────────────────────────────────────────────── */
.callout {
  border-left: 3px solid var(--c-accent);
  background: var(--c-panel2);
  border-radius: 0 8px 8px 0;
  padding: 0.7rem 1rem;
  font-size: 0.88rem;
}
.callout.navy  { border-left-color: var(--c-heading); }
.callout.gold  { border-left-color: var(--c-gold); }
.callout.green { border-left-color: var(--c-green); }
.callout-label {
  display: block;
  color: var(--c-muted);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 0.2rem;
}

/* ─── The declined answer ──────────────────────────────────────────────── */
.refusal {
  border: 1px solid rgba(164, 126, 60, 0.45);
  background: rgba(164, 126, 60, 0.07);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
}
.refusal h4 {
  color: var(--c-gold);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  margin-bottom: 0.35rem;
}

/* ─── Answer block inside a chat bubble ────────────────────────────────── */
.msg.bot.wide { max-width: 100%; }
.answer-figures {
  display: flex;
  gap: 1.6rem;
  flex-wrap: wrap;
  padding: 0.2rem 0 0.6rem;
}
.figure .figure-value {
  color: var(--c-heading);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.figure .figure-value.down { color: var(--c-danger); }
.figure .figure-label {
  color: var(--c-muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ─── Charts ───────────────────────────────────────────────────────────── */
.chart { width: 100%; height: auto; display: block; }
.chart text {
  font-family: 'Metropolis', sans-serif;
  font-size: 11px;
  fill: var(--c-muted);
}
.chart .lbl-strong { fill: var(--c-heading); font-weight: 700; }
.chart .grid-line { stroke: var(--c-line); stroke-width: 1; }
.chart .axis { stroke: #CFCEC8; stroke-width: 1; }

/* Business level relationship graph */
.graph .node rect {
  fill: #FFFFFF;
  stroke: var(--c-chip-border);
  stroke-width: 1.5;
  rx: 8;
}
.graph .node.focus rect {
  fill: rgba(22, 59, 110, 0.07);
  stroke: var(--c-heading);
  stroke-width: 2;
}
.graph .node text { fill: var(--c-heading); font-weight: 700; font-size: 12px; }
.graph .edge { stroke: #B9C2D0; stroke-width: 1.5; fill: none; }
.graph .card-lbl { fill: var(--c-dim); font-size: 10px; }

/* ─── Entrance animation, kept short so scene timing stays predictable ─── */
@keyframes riseIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fade { animation: riseIn 320ms ease-out both; }
.hidden { display: none !important; }

/* ─── Small helpers ────────────────────────────────────────────────────── */
.stack { display: flex; flex-direction: column; gap: 0.75rem; }
.wrap  { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.tiny  { font-size: 0.78rem; }
.num   { font-variant-numeric: tabular-nums; }
.right { text-align: right; }
.sep   { height: 1px; background: var(--c-line); margin: 1rem 0; }
.scrolly { max-height: 21rem; overflow-y: auto; }

/* ═══════════════════════════════════════════════════════════════════════
   Funnel structure. The product is a pipeline, so every page says which
   ring it is: source, mapping, semantic, KPIs, ask. Rings already passed
   read as navy on tint, the current one is solid, the rest are dim.
   ═══════════════════════════════════════════════════════════════════════ */
.funnel {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
  padding: 1.25rem 0 0.25rem;
}
.funnel-step {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-dim);
  padding: 0.28rem 0.62rem;
  border-radius: 6px;
  white-space: nowrap;
}
.funnel-step.done   { color: var(--c-heading); background: rgba(22, 59, 110, 0.07); }
.funnel-step.active { color: #FFFFFF; background: var(--c-heading); }
.funnel-sep  { color: #C4C4BD; font-size: 0.8rem; padding: 0 0.05rem; }
.funnel-note {
  color: var(--c-dim);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-left: 0.5rem;
  padding-left: 0.8rem;
  border-left: 1px solid var(--c-line);
}

/* ─── Business object cards, the centre of the semantic screen ─────────── */
.bo-card {
  background: var(--c-panel);
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1rem 1.15rem;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
.bo-card:hover { border-color: var(--c-chip-border); transform: translateY(-1px); }
.bo-card.open {
  border-color: var(--c-heading);
  box-shadow: 0 0 0 1px var(--c-heading), var(--shadow);
}
.bo-card h3 { margin-bottom: 0.2rem; font-size: 1.05rem; }
.bo-card .bo-def {
  color: var(--c-muted);
  font-size: 0.84rem;
  margin: 0.3rem 0 0.55rem;
}
.bo-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--c-dim);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 0.6rem;
  padding-top: 0.55rem;
  border-top: 1px solid var(--c-line);
}

/* ─── Sample data, shown small so a whole preview fits ────────────────── */
table.sample { font-size: 0.82rem; }
table.sample thead th { font-size: 0.64rem; padding: 0.45rem 0.7rem; }
table.sample tbody td {
  padding: 0.42rem 0.7rem;
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.78rem;
  color: #2A2A2A;
  white-space: nowrap;
}
.sample-wrap { overflow-x: auto; }

/* ─── Column profile: distinct, nulls, and where the mass sits ────────── */
.profile-row {
  display: grid;
  grid-template-columns: 10rem 1fr 4.5rem;
  gap: 0.7rem;
  align-items: center;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--c-line);
  font-size: 0.82rem;
}
.profile-row:last-child { border-bottom: none; }
.profile-bars { display: flex; gap: 2px; height: 14px; align-items: stretch; }
.profile-bars > span {
  display: block;
  border-radius: 2px;
  background: var(--c-heading);
  opacity: 0.85;
}
.profile-bars > span:nth-child(2) { opacity: 0.6; }
.profile-bars > span:nth-child(3) { opacity: 0.42; }
.profile-bars > span:nth-child(4) { opacity: 0.28; }
.profile-bars > span.rest { background: var(--c-line); opacity: 1; }

/* ─── Lineage chain ───────────────────────────────────────────────────── */
.lineage { display: flex; flex-direction: column; gap: 0.35rem; }
.lineage-hop {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.45rem 0.6rem;
  border-left: 2px solid var(--c-line);
  background: var(--c-panel2);
  border-radius: 0 6px 6px 0;
  font-size: 0.83rem;
}
.lineage-hop.last { border-left-color: var(--c-heading); }
.lineage-kind {
  color: var(--c-muted);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ─── Roadmap banner, so nothing here reads as shipping ───────────────── */
.roadmap {
  border: 1px solid rgba(164, 126, 60, 0.45);
  background: rgba(164, 126, 60, 0.08);
  border-radius: var(--radius);
  padding: 0.9rem 1.15rem;
  margin-bottom: 1.5rem;
}
.roadmap strong { color: var(--c-gold); }

/* ─── Edit mode on a business object ─────────────────────────────────── */
.editing { background: rgba(22, 59, 110, 0.04); border-radius: 8px; }
.edit-field {
  width: 100%;
  border: 1px solid var(--c-chip-border);
  border-radius: 8px;
  padding: 0.5rem 0.7rem;
  font-size: 0.88rem;
  color: var(--c-text);
  background: #FFFFFF;
}
textarea.edit-field { min-height: 4.2rem; resize: vertical; }

/* ─── Object list grouped by source system ────────────────────────────── */
.objlist-group {
  color: var(--c-muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.7rem 0.7rem 0.3rem;
  border-top: 1px solid var(--c-line);
  margin-top: 0.35rem;
}
.objlist-group:first-child { border-top: none; margin-top: 0; padding-top: 0.3rem; }
.objlist-group .objlist-sys { color: var(--c-heading); }

/* ─── Small statistics with inline charts ─────────────────────────────── */
.stat-mini {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem 0.8rem;
  align-items: end;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--c-line);
}
.stat-mini:last-child { border-bottom: none; }
.stat-mini .stat-label {
  color: var(--c-muted);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.stat-mini .stat-value {
  color: var(--c-heading);
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stat-mini .stat-chart { grid-column: 1 / -1; }
.spark { width: 100%; height: 34px; display: block; }
.spark rect { fill: var(--c-heading); opacity: 0.75; }
.spark rect.hi { opacity: 1; }
.spark line { stroke: var(--c-line); stroke-width: 1; }

/* ─── Sharing options ────────────────────────────────────────────────── */
.share-row {
  display: grid;
  grid-template-columns: 1.6rem 1fr auto;
  gap: 0.7rem;
  align-items: center;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--c-line);
}
.share-row:last-child { border-bottom: none; }
.share-kind { color: var(--c-heading); font-weight: 700; font-size: 0.9rem; }
.share-note { color: var(--c-muted); font-size: 0.78rem; }
.share-badge {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-heading);
}

/* ─── Reveal on demand, for sample data and profiling ─────────────────── */
.reveal-head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  background: transparent;
  border: 1px dashed var(--c-chip-border);
  border-radius: var(--radius);
  padding: 0.8rem 1.1rem;
  cursor: pointer;
  color: var(--c-heading);
  font-weight: 700;
  font-size: 0.92rem;
  text-align: left;
  transition: background 0.15s;
}
.reveal-head:hover { background: var(--c-panel2); }
.reveal-head .reveal-note {
  color: var(--c-muted);
  font-weight: 400;
  font-size: 0.82rem;
  margin-left: auto;
}

/* ─── Inline editing affordance on table rows ────────────────────────── */
td.cell-edit input, td.cell-edit select, td.cell-edit textarea {
  padding: 0.32rem 0.5rem;
  font-size: 0.85rem;
}
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem 1rem; }
.form-grid .full { grid-column: 1 / -1; }
.form-grid label { margin-bottom: 0.25rem; }

/* Relationship editors need room for the object names, which otherwise
   truncate to things like "Survey Resp" inside a narrow table column. */
.rel-obj select, .rel-card select { min-width: 8.2rem; }

/* ═══════════════════════════════════════════════════════════════════════
   Rebuild, 2026-09-08. The demo now leads with the mechanism rather than
   the finished model, so these are the blocks that mechanism needs.

   Deliberately absent: a stat-tile band at the top of each page. Numbers
   live next to the thing they describe — a confidence beside the proposal
   it scores, an alias count on the glossary row that absorbed them.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Context strip. Replaces the hero: which tenant, which source, what
       state. One line, because it is orientation and not a headline. ──── */
.ctx {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex-wrap: wrap;
  padding: 0.5rem 0 1rem;
  border-bottom: 1px solid var(--c-line);
  margin-bottom: 1.6rem;
}
.ctx-tenant { color: var(--c-heading); font-weight: 700; font-size: 1rem; }
.ctx-sep { color: #C4C4BD; }
.ctx-item { color: var(--c-muted); font-size: 0.85rem; }
.ctx-item code { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.82em; }
.ctx-state {
  color: var(--c-dim);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-left: auto;
  white-space: nowrap;
}

/* ─── A single column proposal: physical name, canonical field, evidence,
       confidence, verdict. The centre of the whole demo. ──────────────── */
.prop {
  display: grid;
  grid-template-columns: 10.5rem 1rem 14rem 1fr 7.5rem;
  gap: 0.7rem;
  align-items: center;
  padding: 0.55rem 0.15rem;
  border-bottom: 1px solid var(--c-line);
}
.prop:last-child { border-bottom: none; }
.prop-src, .prop-dst {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.8rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.prop-src { color: #2A2A2A; }
.prop-dst { color: var(--c-heading); font-weight: 700; }
.prop-arrow { color: var(--c-dim); text-align: center; }
.prop-ev { color: var(--c-muted); font-size: 0.78rem; }
.prop-verdict { justify-self: end; }

/* The abstention. Tinted so it reads as a deliberate stop, not a failure. */
.prop.abstain { background: rgba(164, 126, 60, 0.06); border-radius: 6px; }
.prop.abstain .prop-dst { color: var(--c-gold); font-style: italic; font-weight: 400; }

/* ─── Alias chips: the names one canonical entity has already absorbed ── */
.alias {
  display: inline-block;
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.72rem;
  background: #F4F4F1;
  border: 1px solid var(--c-line);
  border-radius: 5px;
  padding: 0.08rem 0.38rem;
  color: #4A4A4A;
  margin: 0.13rem 0.2rem 0.13rem 0;
}
.alias.new { background: rgba(101, 188, 123, 0.12); border-color: rgba(101, 188, 123, 0.5); color: #3E8A54; }

/* ─── Glossary row ────────────────────────────────────────────────────── */
.gloss {
  padding: 0.85rem 0.2rem;
  border-bottom: 1px solid var(--c-line);
}
.gloss:last-child { border-bottom: none; }
.gloss-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.gloss-name {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--c-heading);
}
.gloss-def { color: var(--c-muted); font-size: 0.84rem; margin: 0.25rem 0 0.4rem; }
.gloss-count {
  margin-left: auto;
  color: var(--c-dim);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ─── What the source does not have. The list nobody volunteers. ──────── */
.gap {
  display: grid;
  grid-template-columns: 13rem 1fr;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.5rem 0.15rem;
  border-bottom: 1px solid var(--c-line);
  font-size: 0.85rem;
}
.gap:last-child { border-bottom: none; }
.gap-field {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.8rem;
  color: var(--c-danger);
}
.gap-cost { color: var(--c-muted); font-size: 0.8rem; }

/* ─── Binding state on an entity's fields ─────────────────────────────── */
.bind {
  display: grid;
  grid-template-columns: 13rem 1fr auto;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.45rem 0.15rem;
  border-bottom: 1px solid var(--c-line);
  font-size: 0.85rem;
}
.bind:last-child { border-bottom: none; }
.bind-field { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.8rem; color: var(--c-heading); font-weight: 700; }
.bind-to { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.78rem; color: #2A2A2A; }
.bind-to.none { color: var(--c-gold); font-family: 'Metropolis', sans-serif; font-style: italic; }

/* ─── Industry coverage ───────────────────────────────────────────────── */
.cov { padding: 1rem 0; border-bottom: 1px solid var(--c-line); }
.cov:last-child { border-bottom: none; }
.cov-head { display: flex; align-items: baseline; gap: 0.7rem; margin-bottom: 0.45rem; }
.cov-name { color: var(--c-heading); font-size: 1.05rem; font-weight: 700; }
.cov-stage { margin-left: auto; }
.cov-note { color: var(--c-muted); font-size: 0.85rem; margin: 0.4rem 0 0.6rem; }
.cov-facts { display: flex; gap: 1.6rem; flex-wrap: wrap; font-size: 0.82rem; }
.cov-fact strong { color: var(--c-heading); font-variant-numeric: tabular-nums; }
.cov-fact span { color: var(--c-dim); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; display: block; }

/* ─── Source table listing ────────────────────────────────────────────── */
td.phys, th.phys { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.82rem; }
tr.excluded td { color: var(--c-dim); }

/* Physical names in a picker need the monospace face too. In Metropolis an
   underscore sits low enough to read as an underline, which turns STOER_MELD
   into STOERMELD at 0.9rem. */
.objlist.phys .objlist-item {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.82rem;
}
.objlist.phys .objlist-item .objlist-meta {
  font-family: 'Metropolis', sans-serif;
  font-size: 0.7rem;
}

/* The tool name and its note are siblings inside one grid cell, so without
   this they abut: "resolve_entityict_incident_register, bound". */
.trace-step .trace-note { display: block; }

/* Sample table headers carry literal column names, underscores and all. */
table.sample thead th {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  text-transform: none;
  letter-spacing: 0;
}

/* ─── Discovered ontology: nodes that came out of a document rather than a
       table are drawn as outlines, because their evidence is weaker and the
       viewer should be able to see that without reading a legend. ───────── */
.graph .node.doc rect {
  fill: rgba(164, 126, 60, 0.06);
  stroke: #A47E3C;
  stroke-dasharray: 5 4;
}
.graph .node.doc text { fill: #A47E3C; }
.graph .edge.weak { stroke: #A47E3C; stroke-dasharray: 5 4; }
.graph .node text.sub { font-size: 10px; font-weight: 400; fill: var(--c-dim); }

/* Evidence row for an inferred join */
.ev {
  display: grid;
  grid-template-columns: 1fr 5.5rem 6rem;
  gap: 0.7rem;
  align-items: center;
  padding: 0.5rem 0.15rem;
  border-bottom: 1px solid var(--c-line);
  font-size: 0.84rem;
}
.ev:last-child { border-bottom: none; }
.ev-join { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.78rem; }
.ev-rate { font-variant-numeric: tabular-nums; color: var(--c-heading); font-weight: 700; }

/* ═══════════════════════════════════════════════════════════════════════
   Mapping. The approval surface, so the row is built around the decision
   rather than around the data: the three actions sit in a fixed column and
   never move, and an accepted row keeps its height so the list does not
   jump under the cursor as it is worked through.
   ═══════════════════════════════════════════════════════════════════════ */
.map-row {
  display: grid;
  grid-template-columns: 9.5rem 1rem 1fr 4.2rem 8.5rem;
  grid-template-areas:
    "src arrow dst conf act"
    "ev  ev    ev  ev   ev";
  gap: 0.2rem 0.6rem;
  align-items: center;
  padding: 0.55rem 0.4rem;
  border-bottom: 1px solid var(--c-line);
  border-left: 3px solid transparent;
  border-radius: 0 6px 6px 0;
}
.map-row:last-child { border-bottom: none; }
.map-src, .map-dst {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.79rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.map-src { color: #2A2A2A; }
.map-dst { color: var(--c-heading); font-weight: 700; }
.map-src { grid-area: src; }
.map-arrow { grid-area: arrow; color: var(--c-dim); text-align: center; }
.map-dst { grid-area: dst; }
.map-conf { grid-area: conf; }
/* Evidence gets its own line, indented under the canonical field it argues
   for. In one row of columns it was squeezed to about 95px and wrapped four
   deep, which made a list of twelve rows unreadable. */
.map-ev {
  grid-area: ev;
  color: var(--c-muted);
  font-size: 0.76rem;
  padding-left: 10.5rem;
}
.map-actions { grid-area: act; display: flex; gap: 0.25rem; justify-content: flex-end; }

.map-row.accepted { border-left-color: var(--c-green); background: rgba(101, 188, 123, 0.06); }
.map-row.changed  { border-left-color: var(--c-heading); background: rgba(22, 59, 110, 0.05); }
.map-row.skipped  { border-left-color: var(--c-dim); opacity: 0.6; }
.map-row.abstain  { border-left-color: var(--c-gold); background: rgba(164, 126, 60, 0.06); }
.map-row.abstain .map-dst { color: var(--c-gold); font-style: italic; font-weight: 400; }

.btn-mini {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.22rem 0.5rem;
  border-radius: 6px;
  border: 1px solid var(--c-chip-border);
  background: transparent;
  color: var(--c-heading);
  cursor: pointer;
}
.btn-mini:hover { background: var(--c-panel2); }
.btn-mini.go { background: var(--c-heading); border-color: var(--c-heading); color: #FFF; }
.btn-mini:disabled { opacity: 0.45; cursor: default; }
.map-state {
  grid-area: act;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; text-align: right; white-space: nowrap;
}
.map-state.ok   { color: #3E8A54; }
.map-state.ch   { color: var(--c-heading); }
.map-state.sk   { color: var(--c-dim); }

/* The queue down the side, one row per proposal */
.q-item {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 1px solid transparent;
  border-left: 3px solid var(--c-line);
  border-radius: 0 8px 8px 0;
  padding: 0.5rem 0.7rem; cursor: pointer; color: var(--c-text);
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 0.79rem;
}
.q-item:hover { background: var(--c-panel2); }
.q-item.active { background: rgba(22, 59, 110, 0.07); border-color: var(--c-chip-border); border-left-color: var(--c-heading); font-weight: 700; }
.q-item.done { border-left-color: var(--c-green); }
.q-meta {
  display: block; font-family: 'Metropolis', sans-serif;
  color: var(--c-dim); font-size: 0.7rem; font-weight: 400; letter-spacing: 0.03em;
}
.kbd {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.72rem; background: #F4F4F1; border: 1px solid var(--c-line);
  border-bottom-width: 2px; border-radius: 4px; padding: 0.05rem 0.32rem; color: #2A2A2A;
}
/* The mapping queue holds names like "Kritischer Geschäftsprozess". */
.split-q { grid-template-columns: 19rem 1fr; }

.btn:disabled { opacity: 0.5; cursor: default; }

/* The canonical field table. The description is the column that matters — it
   is what the matcher compares a customer's column against — so it gets the
   room, and the fixed layout stops a long example from stealing it back. */
table.fieldtable { table-layout: fixed; }
table.fieldtable th:nth-child(1), table.fieldtable td:nth-child(1) { width: 11rem; }
table.fieldtable th:nth-child(2), table.fieldtable td:nth-child(2) { width: 6.5rem; }
table.fieldtable th:nth-child(3), table.fieldtable td:nth-child(3) { width: 3rem; }
table.fieldtable th:nth-child(5), table.fieldtable td:nth-child(5) { width: 9rem; }
table.fieldtable td { vertical-align: top; overflow-wrap: anywhere; }

/* ccp_transaction_recovery_specification does not fit on one line anywhere. */
.objlist.phys .objlist-item { overflow-wrap: anywhere; }

/* Node labels in the discovered graph are physical table names, so they need
   the monospace face for the underscores to survive. */
.graph .node text { font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 11px; }
.graph .node text.sub { font-family: 'Metropolis', sans-serif; font-size: 10px; }

/* ═══════════════════════════════════════════════════════════════════════
   Interactive ER graph (assets/er.js). Two screens share it: the canonical
   model and the ontology discovered at a tenant. Selection dims everything
   it is not about, because a diagram of 66 boxes is only readable when it
   can be reduced to the part being talked about.
   ═══════════════════════════════════════════════════════════════════════ */
.er-wrap {
  position: relative;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  background: var(--c-panel);
  overflow: hidden;
}
svg.er { width: 100%; height: auto; display: block; cursor: grab; touch-action: none; }
svg.er.grabbing { cursor: grabbing; }

.er-node rect { fill: #FFFFFF; stroke: var(--c-chip-border); stroke-width: 1.4; }
.er-node text {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 11px; fill: var(--c-heading); font-weight: 700;
  pointer-events: none; user-select: none;
}
.er-node text.sub { font-family: 'Metropolis', sans-serif; font-size: 9px; fill: var(--c-dim); font-weight: 400; }
.er-node { cursor: pointer; }
.er-node:hover rect { stroke: var(--c-heading); }

.er-node.orphan rect { fill: var(--c-panel2); stroke: #CFCEC8; stroke-dasharray: 4 3; }
.er-node.orphan text { fill: var(--c-dim); }
.er-node.doc rect { fill: rgba(164, 126, 60, 0.06); stroke: var(--c-gold); stroke-dasharray: 5 4; }
.er-node.doc text { fill: var(--c-gold); }
.er-node.sel rect { stroke: var(--c-heading); stroke-width: 2.4; fill: rgba(22, 59, 110, 0.06); }
.er-node.dim { opacity: 0.16; }

.er-edge { stroke: #B9C2D0; stroke-width: 1.4; fill: none; }
.er-edge.described, .er-edge.weak { stroke: #CBB998; stroke-dasharray: 5 4; }
.er-edge.declared { stroke: var(--c-green); stroke-width: 1.8; }
.er-edge.sel { stroke: var(--c-heading); stroke-width: 2.6; stroke-dasharray: none; }
.er-edge.approved { stroke: var(--c-green); stroke-width: 2.2; stroke-dasharray: none; }
.er-edge.rejected { stroke: #D6D4CD; stroke-width: 1.2; stroke-dasharray: 2 4; }
.er-edge.dim { opacity: 0.12; }
/* A 1.4px line is not a click target. */
.er-hit { stroke: transparent; stroke-width: 14; cursor: pointer; }

.er-elbl {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 8.5px; fill: var(--c-dim); pointer-events: none; user-select: none;
}
.er-elbl.sel { fill: var(--c-heading); font-size: 10px; font-weight: 700; }
.er-band {
  font-family: 'Metropolis', sans-serif; font-size: 12px; fill: var(--c-dim);
  font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  pointer-events: none; user-select: none;
}
.er-stub line { stroke: var(--c-gold); stroke-width: 1.4; stroke-dasharray: 3 3; }
.er-stub circle { fill: none; stroke: var(--c-gold); stroke-width: 1.4; }
.er-stub text { font-family: 'Metropolis', sans-serif; font-size: 9px; fill: var(--c-gold); font-weight: 700; }
.er-stub.dim { opacity: 0.16; }

/* Controls float over the canvas so they do not consume diagram height. */
.er-ctl {
  position: absolute; top: 0.7rem; right: 0.7rem;
  display: flex; gap: 0.3rem; align-items: center;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--c-line); border-radius: 9px; padding: 0.3rem;
}
.er-ctl input { width: 13rem; padding: 0.28rem 0.55rem; font-size: 0.8rem; border-radius: 6px; }
.er-legend {
  position: absolute; left: 0.7rem; bottom: 0.7rem;
  display: flex; gap: 0.9rem; flex-wrap: wrap;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--c-line); border-radius: 9px; padding: 0.4rem 0.7rem;
  font-size: 0.7rem; color: var(--c-muted);
}
.er-legend i { display: inline-block; width: 18px; height: 0; vertical-align: middle;
               border-top: 2px solid #B9C2D0; margin-right: 0.35rem; }
.er-legend i.g { border-top-color: var(--c-green); }
.er-legend i.d { border-top: 2px dashed #CBB998; }
.er-legend i.b { border-top: none; width: 12px; height: 10px; border: 1.4px solid var(--c-chip-border); border-radius: 3px; }
.er-legend i.o { border-top: none; width: 12px; height: 10px; border: 1.4px dashed #CFCEC8; border-radius: 3px; }

.er-panel { position: sticky; top: calc(var(--nav-h) + 1rem); }
h3.tiny-h { font-size: 0.92rem; line-height: 1.5; font-family: 'SFMono-Regular', Menlo, Consolas, monospace; }

/* The two diagram pages need more width than the reading pages. The nav is
   widened with them so the brand stays over the left edge of the content. */
body.wide .nav-inner, body.wide .container { max-width: 92rem; }
body.wide .split-wide { grid-template-columns: 1fr 21rem; }

.er-legend i.doc {
  border-top: none; width: 12px; height: 10px;
  border: 1.4px dashed var(--c-gold); border-radius: 3px;
  background: rgba(164, 126, 60, 0.06);
}

/* ═══════════════════════════════════════════════════════════════════════
   Import. The drop zone is the page: the first question anyone asks about
   a canonical model is where the file goes, so it is the largest thing on
   screen rather than a filename printed above a button.
   ═══════════════════════════════════════════════════════════════════════ */
.dropzone {
  border: 2px dashed var(--c-chip-border);
  border-radius: var(--radius);
  background: var(--c-panel2);
  padding: 2.4rem 1.5rem;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.dropzone:hover { background: rgba(22, 59, 110, 0.04); }
.dropzone.over {
  border-color: var(--c-heading);
  border-style: solid;
  background: rgba(22, 59, 110, 0.07);
}
.dropzone.bad { border-color: var(--c-danger); background: rgba(192, 57, 43, 0.06); }
.dz-icon { font-size: 1.7rem; line-height: 1; color: var(--c-chip-border); }
.dz-title { color: var(--c-heading); font-weight: 700; font-size: 1.05rem; margin-top: 0.5rem; }
.dz-sub { color: var(--c-muted); font-size: 0.85rem; margin-top: 0.25rem; }
.dz-types { display: flex; gap: 0.35rem; justify-content: center; flex-wrap: wrap; margin-top: 0.9rem; }

.staged {
  display: grid;
  grid-template-columns: 2.6rem 1fr auto;
  gap: 0.8rem;
  align-items: center;
  border: 1px solid var(--c-line);
  border-radius: 10px;
  background: var(--c-panel);
  padding: 0.7rem 0.9rem;
  margin-top: 0.8rem;
}
.staged-name {
  display: block;
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.84rem; color: #2A2A2A; overflow-wrap: anywhere;
}
.staged-meta { display: block; color: var(--c-muted); font-size: 0.76rem; margin-top: 0.15rem; }
/* The extension is a better icon than a glyph: it renders everywhere and it
   says which converter is about to run. */
.staged-icon {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--c-heading); text-align: center;
  border: 1px solid var(--c-chip-border); border-radius: 5px;
  padding: 0.3rem 0.1rem; background: var(--c-panel2);
}

/* Alternate intake routes, folded away until wanted */
.route {
  border: 1px solid var(--c-line);
  border-radius: 10px;
  padding: 0.6rem 0.85rem;
  margin-top: 0.5rem;
}
.route summary {
  cursor: pointer; color: var(--c-heading); font-weight: 700; font-size: 0.86rem;
  list-style: none; display: flex; align-items: center; gap: 0.5rem;
}
.route summary::-webkit-details-marker { display: none; }
.route summary::before { content: '+'; color: var(--c-dim); font-weight: 700; }
.route[open] summary::before { content: '\2212'; }
.route .route-body { margin-top: 0.7rem; }

/* The side panel now carries every field of the selected entity, so it has to
   scroll on its own rather than stretching the page past the diagram. */
.er-panel { max-height: calc(100vh - var(--nav-h) - 3rem); overflow-y: auto; }

/* One field inside that panel: name, type, what it means, what it links to. */
.pf { padding: 0.5rem 0; border-bottom: 1px solid var(--c-line); }
.pf:last-child { border-bottom: none; }
.pf-head { display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; }
.pf-name {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.78rem; color: var(--c-heading); font-weight: 700; overflow-wrap: anywhere;
}
.pf-type {
  color: var(--c-dim); font-size: 0.64rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.pf-req { color: var(--c-danger); font-size: 0.64rem; font-weight: 700; letter-spacing: 0.08em; }
.pf-def { color: var(--c-muted); font-size: 0.76rem; margin-top: 0.2rem; }
.pf-ex { color: var(--c-dim); font-size: 0.72rem; margin-top: 0.15rem;
         font-family: 'SFMono-Regular', Menlo, Consolas, monospace; overflow-wrap: anywhere; }
.pf-link { color: var(--c-heading); font-size: 0.72rem; margin-top: 0.2rem; }
.pf-link code { font-size: 0.95em; }

/* ═══════════════════════════════════════════════════════════════════════
   Connecting a source. The connector is picked first because it decides
   what the rest of the form even asks for: an RDS instance wants an IAM
   role or a secret ARN, a Snowflake account wants a key pair, an ODBC DSN
   wants a driver and a connection string. One form for all of them asks
   for the union and fits none.
   ═══════════════════════════════════════════════════════════════════════ */
.conn-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.55rem;
}
.conn-tile {
  border: 1px solid var(--c-line);
  border-radius: 10px;
  background: var(--c-panel);
  padding: 0.6rem 0.7rem;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, background 0.15s;
}
.conn-tile:hover { border-color: var(--c-chip-border); background: var(--c-panel2); }
.conn-tile.on {
  border-color: var(--c-heading);
  background: rgba(22, 59, 110, 0.06);
  box-shadow: inset 0 0 0 1px var(--c-heading);
}
.conn-name { color: var(--c-heading); font-weight: 700; font-size: 0.86rem; }
.conn-kind {
  display: block; color: var(--c-dim); font-size: 0.66rem;
  font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; margin-top: 0.1rem;
}
.conn-tile.soon { opacity: 0.55; }

/* The test result, which is the only thing on the form that is not a claim */
.probe { display: grid; grid-template-columns: 1.3rem 1fr auto; gap: 0.6rem;
         align-items: center; padding: 0.4rem 0; border-bottom: 1px solid var(--c-line);
         font-size: 0.83rem; }
.probe:last-child { border-bottom: none; }
.probe-mark { text-align: center; font-weight: 700; }
.probe.ok   .probe-mark { color: #3E8A54; }
.probe.warn .probe-mark { color: var(--c-gold); }
.probe.bad  .probe-mark { color: var(--c-danger); }
.probe-note { color: var(--c-muted); font-size: 0.76rem; }
.probe-ms { color: var(--c-dim); font-size: 0.74rem; font-variant-numeric: tabular-nums; }

/* Delivery: one binding, several consumers */
.consumer {
  display: grid;
  grid-template-columns: 1.5fr 1fr auto;
  gap: 0.8rem;
  align-items: start;
  padding: 0.8rem 0.2rem;
  border-bottom: 1px solid var(--c-line);
}
.consumer:last-child { border-bottom: none; }
.consumer-name { color: var(--c-heading); font-weight: 700; font-size: 0.95rem; }
.consumer-what { color: var(--c-muted); font-size: 0.82rem; margin-top: 0.2rem; }
.consumer-gets { font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
                 font-size: 0.76rem; color: #2A2A2A; overflow-wrap: anywhere; }

.mode {
  border: 1px solid var(--c-line);
  border-left: 3px solid var(--c-line);
  border-radius: 0 10px 10px 0;
  padding: 0.8rem 1rem;
  cursor: pointer;
}
.mode.on { border-color: var(--c-chip-border); border-left-color: var(--c-heading);
           background: rgba(22, 59, 110, 0.04); }
.mode h4 { color: var(--c-heading); font-size: 0.95rem; }
.mode p { color: var(--c-muted); font-size: 0.82rem; margin-top: 0.3rem; }

/* The binding sits beside a shorter card, and the grid stretches both to the
   same height. Let the scrolling block take the slack rather than leaving a
   band of empty card under it. */
.card.fill { display: flex; flex-direction: column; }
.card.fill .mono { flex: 1; min-height: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   Transform. The canonical model is the fixed point, so the customer's
   data is what bends. This screen is where the bending is written down,
   tested against real values, and — the part that matters — where the
   rows it fails on are counted rather than dropped.
   ═══════════════════════════════════════════════════════════════════════ */
.xf-row {
  display: grid;
  grid-template-columns: 1fr 6rem;
  gap: 0.5rem;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border: 1px solid transparent;
  border-left: 3px solid var(--c-line);
  border-radius: 0 8px 8px 0;
  cursor: pointer;
  width: 100%;
  text-align: left;
  background: transparent;
}
.xf-row:hover { background: var(--c-panel2); }
.xf-row.on { background: rgba(22, 59, 110, 0.07); border-color: var(--c-chip-border);
             border-left-color: var(--c-heading); }
.xf-row.done { border-left-color: var(--c-green); }
.xf-row.blocked { border-left-color: var(--c-danger); }
.xf-field { font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
            font-size: 0.79rem; color: var(--c-heading); font-weight: 700; overflow-wrap: anywhere; }
.xf-why { display: block; color: var(--c-muted); font-size: 0.72rem; margin-top: 0.15rem; }
.xf-kind { justify-self: end; font-size: 0.62rem; font-weight: 700;
           letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-dim); white-space: nowrap; }

/* The expression, and the rows it was run against */
.xf-expr {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.82rem; line-height: 1.6;
  background: #F4F4F1; border: 1px solid var(--c-line); border-radius: 8px;
  padding: 0.7rem 0.9rem; color: #2A2A2A; width: 100%; resize: vertical; min-height: 4.5rem;
}
table.xf-prev { font-size: 0.8rem; }
table.xf-prev td { font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
                   font-size: 0.78rem; padding: 0.4rem 0.7rem; }
table.xf-prev tr.bad td { background: rgba(192, 57, 43, 0.05); color: var(--c-danger); }
table.xf-prev tr.bad td:first-child { color: #2A2A2A; }
.xf-arrow { color: var(--c-dim); text-align: center; width: 2rem; }

.xf-stat { display: flex; gap: 1.6rem; flex-wrap: wrap; padding: 0.2rem 0 0.4rem; }
.xf-stat b { color: var(--c-heading); font-size: 1.15rem; font-variant-numeric: tabular-nums; }
.xf-stat b.bad { color: var(--c-danger); }
.xf-stat span { display: block; color: var(--c-dim); font-size: 0.64rem;
                font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; }

.runs {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.18rem 0.5rem; border-radius: 6px;
}
.runs.push { background: rgba(101, 188, 123, 0.14); color: #3E8A54; }
.runs.plat { background: rgba(22, 59, 110, 0.10); color: var(--c-heading); }
/* A qualified field name breaks mid-word in a 19rem column, so the entity goes
   on its own line above the field rather than being hyphenated into it. */
.xf-ent {
  display: block;
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.68rem; color: var(--c-dim); overflow-wrap: anywhere;
}

/* A mapping whose shapes do not match is only half a decision. The link is on
   the evidence line rather than in the action column, because it is not a
   fourth button: it is a consequence of accepting. */
a.needs-xf {
  color: var(--c-gold);
  font-weight: 700;
  white-space: nowrap;
}
a.needs-xf:hover { text-decoration: underline; }

/* ═══════════════════════════════════════════════════════════════════════
   Computed fields. A column that matches nothing on its own is not always
   a dead end: several of them together often produce a canonical field
   that none of them produces alone. That proposal has a different shape
   from a column-to-column one, so it gets its own block rather than being
   squeezed into the mapping row.
   ═══════════════════════════════════════════════════════════════════════ */
.comp {
  border: 1px solid var(--c-line);
  border-left: 3px solid var(--c-heading);
  border-radius: 0 10px 10px 0;
  padding: 0.85rem 1rem;
  margin-top: 0.6rem;
  background: rgba(22, 59, 110, 0.03);
}
.comp.derived { border-left-color: var(--c-gold); background: rgba(164, 126, 60, 0.05); }
.comp.accepted { border-left-color: var(--c-green); background: rgba(101, 188, 123, 0.06); }
.comp.rejected { opacity: 0.55; border-left-color: var(--c-dim); }
.comp-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.comp-target {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.88rem; font-weight: 700; color: var(--c-heading);
}
.comp-from { color: var(--c-muted); font-size: 0.78rem; margin-top: 0.3rem; }
.comp-from code { font-size: 0.95em; }
.comp-expr {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 0.76rem; background: #F4F4F1; border: 1px solid var(--c-line);
  border-radius: 6px; padding: 0.45rem 0.65rem; margin-top: 0.5rem;
  color: #2A2A2A; white-space: pre-wrap;
}
.comp-note { color: var(--c-muted); font-size: 0.78rem; margin-top: 0.5rem; }
.comp-block {
  color: var(--c-danger); font-size: 0.78rem; margin-top: 0.4rem;
  padding-left: 0.7rem; border-left: 2px solid rgba(192, 57, 43, 0.35);
}

/* An entity that has been mapped and, where needed, reshaped. The discovered
   ontology and the bound one are the same drawing at two moments, so the
   difference has to be visible without moving a single box. */
.er-node.bound rect { stroke: var(--c-green); stroke-width: 2; fill: rgba(101, 188, 123, 0.06); }
.er-node.bound text.sub { fill: #3E8A54; }
.er-node.held rect { stroke: var(--c-gold); stroke-dasharray: 4 3; fill: rgba(164, 126, 60, 0.05); }
.er-node.held text, .er-node.held text.sub { fill: var(--c-gold); }
