/* X.4.b.3 — Studio diagram chrome + SVG dim/focus styles.
 *
 * X.4.f.13 — ``--studio-*`` tokens now alias App2's ``--color-*``
 * Tailwind tokens (``input.css``'s ``@theme`` block). The studio
 * HTML chrome links App2's compiled ``output.css`` AND injects the
 * per-L2-instance ``:root { --color-accent: ...; }`` override block
 * via ``render._emit_theme_style``, so the studio inherits the
 * active L2 institution's brand palette. Hardcoded fallbacks here
 * cover the standalone-CSS-load case (e.g., a screenshot harness
 * loading just diagram.css without the page chrome).
 */

:root {
  --studio-bg: var(--color-surface-bg, #f8fafc);
  --studio-fg: var(--color-primary-fg, #1e293b);
  --studio-muted: var(--color-secondary-fg, #64748b);
  --studio-border: var(--color-surface-border, #cbd5e1);
  --studio-accent: var(--color-accent, #1f4e79);
  --studio-tint: var(--color-link-tint, #e0e7f0);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    sans-serif;
  background: var(--studio-bg);
  color: var(--studio-fg);
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.studio-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--studio-border);
  background: white;
  flex: 0 0 auto;
}

.studio-header h1 {
  font-size: 1rem;
  margin: 0;
  font-weight: 600;
  color: var(--studio-accent);
}

.studio-header .instance {
  color: var(--studio-muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.875rem;
}

.studio-header .nav-link {
  color: var(--studio-accent);
  text-decoration: none;
  font-size: 0.875rem;
}

.studio-header .nav-link:hover {
  text-decoration: underline;
}

/* X.4.g.14 — Deploy changes button + status indicator. */
.studio-header .deploy-btn {
  margin-left: auto;
  padding: 0.4rem 0.85rem;
  font-size: 0.875rem;
  font-weight: 500;
  background: var(--studio-accent);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.studio-header .deploy-btn:hover:not(:disabled) {
  filter: brightness(1.1);
}

.studio-header .deploy-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.studio-header .deploy-status {
  font-size: 0.875rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  min-width: 0;
}

.studio-header .deploy-status--running {
  color: var(--studio-muted);
}

.studio-header .deploy-status--ok {
  color: #2f7a3a;
}

.studio-header .deploy-status--halted,
.studio-header .deploy-status--error {
  color: #b1231f;
}

.diagram-chrome {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--studio-border);
  background: white;
  flex: 0 0 auto;
}

.diagram-chrome label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  cursor: pointer;
  font-size: 0.875rem;
  user-select: none;
}

.diagram-chrome .count {
  color: var(--studio-muted);
  font-size: 0.75rem;
}

.diagram-chrome button {
  background: var(--studio-tint);
  color: var(--studio-accent);
  border: 1px solid var(--studio-border);
  padding: 0.25rem 0.75rem;
  border-radius: 0.25rem;
  cursor: pointer;
  font-size: 0.875rem;
}

.diagram-chrome button:hover {
  background: var(--studio-accent);
  color: white;
}

.diagram-chrome .status {
  margin-left: auto;
  color: var(--studio-muted);
  font-size: 0.75rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.diagram-chrome .knob {
  font-size: 0.75rem;
  color: var(--studio-muted);
}

.diagram-chrome .knob a {
  color: var(--studio-accent);
  text-decoration: none;
  margin-right: 0.5rem;
}

.diagram-chrome .knob a.active {
  font-weight: 600;
  text-decoration: underline;
}

/* Engine hot-swap link styling — pill-style chip, distinct active state
 * so the user can see at a glance which layout engine is rendering. */
.diagram-chrome .knob .engine-link {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--studio-border);
  border-radius: 0.2rem;
  background: white;
  margin-right: 0.2rem;
  text-decoration: none;
  font-weight: 500;
  font-size: 0.78rem;
}
.diagram-chrome .knob .engine-link:hover {
  background: var(--studio-tint);
}
.diagram-chrome .knob .engine-link.active {
  background: var(--studio-accent);
  color: white;
  border-color: var(--studio-accent);
  text-decoration: none;
}

/* Pan/zoom — let the cursor signal grab affordance on the SVG canvas. */
.topology-svg {
  cursor: grab;
}
.topology-svg:active {
  cursor: grabbing;
}

.diagram-viewport {
  flex: 1 1 auto;
  /* hidden, not auto — the SVG fits to viewBox via preserveAspectRatio.
   * Pan/zoom modifies the viewBox, not the rendered pixel size, so we
   * never want browser scrollbars. */
  overflow: hidden;
  padding: 1rem;
  background: white;
  /* min-height: 0 lets the flex item actually shrink below its content's
   * intrinsic size — without this, flex falls back to content size and
   * the viewport stretches taller than the window. */
  min-height: 0;
  display: flex;
}

#diagram-target {
  /* Wrapper around the injected SVG; flex:1 + min-height:0 so the SVG
   * fills the viewport in BOTH dimensions, not just width. */
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
}

.topology-svg {
  display: block;
  width: 100%;
  height: 100%;
  /* No min-height — let preserveAspectRatio="xMidYMid meet" (SVG default)
   * fit the viewBox inside the container, both dimensions. min-height
   * was forcing 400px floor and breaking the height fit on short
   * viewports. */
}

/* Chrome section labels (Show: / Edge labels:). */
.diagram-chrome .chrome-section-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--studio-muted);
  margin-right: -0.5rem;
}

/* Visibility toggles — driven by checkboxes via JS adding hide-<kind>
 * classes on the SVG root. Role-scope split per X.4.b chrome iteration D. */
.topology-svg.hide-role-internal g.node[data-kind="role"][data-scope="internal"] { display: none; }
.topology-svg.hide-role-external g.node[data-kind="role"][data-scope="external"] { display: none; }
.topology-svg.hide-rail g.node[data-kind="rail"] { display: none; }
.topology-svg.hide-template g.node[data-kind="template"] { display: none; }
.topology-svg.hide-chain g.edge[data-kind="chain"] { display: none; }

/* Hiding a role-scope also hides edges whose endpoint is that scope. */
.topology-svg.hide-role-internal g.edge[data-source^="role__"][data-target^="role__"] {
  /* Conservatively keep the edge unless BOTH endpoints are hidden (not
   * trivially expressible in CSS without per-edge data-scope flags).
   * In practice the dangling visual is rare since rail bundles usually
   * span internal+external — cross-perimeter rails. Future iteration
   * can stamp data-source-scope on each edge if this gets noisy. */
}

/* When templates are hidden, hide their member edges. */
.topology-svg.hide-template g.edge[data-kind="template_member"] {
  display: none;
}

/* Per-kind edge-label toggles (X.4.b chrome iteration A). The SVG's
 * <text> elements inside g.edge are graphviz's edge labels. */
.topology-svg.hide-edge-label-rail_bundle g.edge[data-kind="rail_bundle"] text { display: none; }
.topology-svg.hide-edge-label-self_loop g.edge[data-kind="self_loop"] text { display: none; }
.topology-svg.hide-edge-label-chain g.edge[data-kind="chain"] text { display: none; }

/* Conceptual layer stepper — server-rendered. The chrome's
 * `<a class="layer-btn" href="?layer=N">` links navigate; the server
 * filters the topology emit and dot re-lays-out the smaller subset
 * cleanly. No CSS visibility hides for layers — the DOT itself only
 * contains what the layer should show. */

/* Per-kind hide for control_parent edges (the chrome edge-label toggle). */
.topology-svg.hide-control_parent g.edge[data-kind="control_parent"] {
  display: none;
}
.topology-svg.hide-edge-label-control_parent g.edge[data-kind="control_parent"] text {
  display: none;
}

/* Layer stepper button styling — pill group inside .diagram-chrome. */
.diagram-chrome .layer-stepper {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  color: var(--studio-muted);
}
.diagram-chrome .layer-btn {
  background: white;
  color: var(--studio-fg);
  border: 1px solid var(--studio-border);
  padding: 0.2rem 0.6rem;
  border-radius: 0.2rem;
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 500;
}
.diagram-chrome .layer-btn:hover {
  background: var(--studio-tint);
}
.diagram-chrome .layer-btn.active {
  background: var(--studio-accent);
  color: white;
  border-color: var(--studio-accent);
}

/* Click affordance on nodes. Hover highlight stays — click-to-focus
 * is now URL navigation (X.4.b focus, 2026-05-13), not in-place
 * dimming, so the .dim / .focus / .focused selectors that lived here
 * have been dropped. The hover lift remains so the user knows nodes
 * are interactive. */
.topology-svg g.node:hover {
  filter: brightness(1.05) drop-shadow(0 0 3px rgba(31, 78, 121, 0.4));
}

.topology-svg text {
  user-select: none;
}

/* X.4.c.5.d/e — Coverage overlay. The chrome's #toggle-coverage
 * checkbox toggles `.coverage-on` on the SVG root; the JS shim has
 * already stamped `data-presence="yes|no"` per node + edge by then.
 * Absent (`no`) entities desaturate to a muted grey so the operator's
 * eye lands on the missing-ETL gaps; present entities stay normal.
 * Hover tooltips (the SVG <title>) carry the row count so the
 * integrator can spot-check magnitudes without leaving the diagram. */
.topology-svg.coverage-on g.node[data-presence="no"] > polygon,
.topology-svg.coverage-on g.node[data-presence="no"] > ellipse,
.topology-svg.coverage-on g.node[data-presence="no"] > path {
  fill: #f1f5f9 !important;
  stroke: #cbd5e1 !important;
}
.topology-svg.coverage-on g.node[data-presence="no"] text {
  fill: #94a3b8 !important;
}
.topology-svg.coverage-on g.edge[data-presence="no"] path,
.topology-svg.coverage-on g.edge[data-presence="no"] polygon {
  stroke: #cbd5e1 !important;
  fill: #cbd5e1 !important;
  opacity: 0.5;
}
/* Coverage chrome toggle — pill style mirroring the layer-btn look so
 * it sits comfortably alongside the layer stepper + Reset button. */
.diagram-chrome .chrome-coverage-toggle,
.diagram-chrome .chrome-trainer-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  color: var(--studio-muted);
  cursor: pointer;
  user-select: none;
}

/* X.4.c.6 — Trainer overlay. Nodes with planted exceptions get a
 * warning-coloured outline (amber) + a thicker stroke so the trainer
 * spots them at a glance. The hover <title> carries the per-kind
 * counts (drift×2, overdraft×1, etc.). Combines additively with the
 * coverage tint — a trainer-marked absent node is still grey, just
 * with the amber outline.
 */
.topology-svg.trainer-on g.node[data-trainer-kinds] > polygon,
.topology-svg.trainer-on g.node[data-trainer-kinds] > ellipse,
.topology-svg.trainer-on g.node[data-trainer-kinds] > path {
  stroke: #f59e0b !important;
  stroke-width: 3px !important;
}
