/* ═══════════════════════════════════════════════════════════════════
   Workflow step graph + scheduling/sharing panels (M5 follow-up).

   Kept in its own sheet rather than folded into components.css: these
   classes belong to one feature, and the two pages that draw a graph
   (/workflows and the admin Workflows tab) can then load it explicitly.

   Every colour is a token, so light/dark and tenant theming follow with
   no per-mode rules here. Direction: no physical left/right properties
   — the SVG itself is laid out top-to-bottom precisely so RTL needs no
   mirroring.
   ═══════════════════════════════════════════════════════════════════ */

/* ── canvas ───────────────────────────────────────────────────────── */
.wfg-canvas {
  position: relative;
  overflow: auto;                 /* a wide fork scrolls in its own box */
  max-height: 62vh;
  padding: 4px;
  border: 1px solid var(--card-b);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  /* Faint dot grid: reads as a canvas without competing with the nodes. */
  background-image: radial-gradient(circle at 1px 1px,
                    color-mix(in srgb, var(--muted) 26%, transparent) 1px, transparent 0);
  background-size: 16px 16px;
}

.wfg-canvas.is-compact { max-height: 40vh; }

.wfg-svg { display: block; margin-inline: auto; }

/* ── nodes ────────────────────────────────────────────────────────── */
.wfg-node .wfg-box {
  fill: var(--card);
  stroke: var(--card-b);
  stroke-width: 1;
}

.wfg-node .wfg-bar { fill: var(--wfg-accent, var(--muted)); }

.wfg-node .wfg-dot { fill: var(--wfg-accent, var(--muted)); }

.wfg-node .wfg-id {
  fill: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.wfg-node .wfg-type {
  fill: var(--wfg-accent, var(--muted));
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.wfg-node .wfg-summary {
  fill: var(--muted);
  font-size: 10.5px;
}

.wfg-node .wfg-chip { fill: var(--ok); }
.wfg-node .wfg-chip-text {
  fill: #fff;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.wfg-node:focus-visible { outline: none; }
.wfg-node:focus-visible .wfg-box,
.wfg-node:hover .wfg-box {
  stroke: var(--wfg-accent, var(--accent));
  stroke-width: 1.6;
}

/* A park is where a run waits on a human or a clock — dashed, because the box
   is not "work happening", it is work suspended. */
.wfg-node.is-park .wfg-box { stroke-dasharray: 6 4; }

.wfg-node.is-terminal .wfg-box {
  fill: color-mix(in srgb, var(--ok) 10%, var(--card));
}

/* Where the run is right now. */
.wfg-node.is-current .wfg-box {
  stroke: var(--wfg-accent, var(--accent));
  stroke-width: 2.4;
  fill: color-mix(in srgb, var(--wfg-accent, var(--accent)) 12%, var(--card));
}

.wfg-node.is-current .wfg-dot { animation: wfg-pulse 1.8s ease-in-out infinite; }

/* Already passed: present, but visually behind the live position. */
.wfg-node.is-visited { opacity: 0.62; }

/* A structural defect in the definition (unreachable step). */
.wfg-node.is-problem .wfg-box {
  stroke: var(--danger);
  stroke-dasharray: 3 3;
}

/* Opacity only — the SVG `r` attribute is animatable as a CSS property in some
   engines and not others, and a dot that changes size in Chrome but not Firefox
   is worse than one that only fades. */
@keyframes wfg-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .wfg-node.is-current .wfg-dot { animation: none; }
}

/* ── edges ────────────────────────────────────────────────────────── */
.wfg-edge { stroke-linecap: round; stroke-linejoin: round; }

.wfg-edge-label {
  fill: var(--muted);
  font-size: 10px;
  font-weight: 600;
}

/* ── legend ───────────────────────────────────────────────────────── */
.wfg-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-block-start: 8px;
  font-size: 11px;
  color: var(--muted);
}

.wfg-legend-item { display: inline-flex; align-items: center; gap: 5px; }

.wfg-legend-swatch {
  display: inline-block;
  width: 14px;
  height: 2px;
  border-radius: 2px;
}

/* ── problems banner (broken branch target, unreachable step) ─────── */
.wfg-problems {
  margin-block-start: 10px;
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  font-size: 12px;
  color: var(--text);
}

.wfg-problems ul { margin: 6px 0 0; padding-inline-start: 18px; }
.wfg-problems li { margin-block: 2px; }

/* ── sub-tab strip (Instances | Schedules | Definitions) ──────────── */
.wf-subtabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-block-end: 14px;
  border-block-end: 1px solid var(--card-b);
  padding-block-end: 8px;
}

.wf-subtab {
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--muted);
  padding: 6px 14px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

.wf-subtab:hover { color: var(--text); background: var(--surface-b); }

.wf-subtab[aria-selected="true"] {
  color: var(--text);
  background: var(--accent-soft, var(--surface-b));
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

/* ── schedule + share tables/cards ────────────────────────────────── */
.wf-cron {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  background: var(--surface-b);
}

.wf-next-run { font-size: 12px; color: var(--text); }
.wf-next-run.is-unscheduled { color: var(--warn); }

.wf-grant-caps { display: inline-flex; gap: 5px; flex-wrap: wrap; }

.wf-def-card {
  border: 1px solid var(--card-b);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 14px 16px;
  margin-block-end: 10px;
}

.wf-def-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  justify-content: space-between;
}

.wf-def-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  color: var(--muted);
}

.wf-def-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-block-start: 8px;
  font-size: 11.5px;
  color: var(--muted);
}

.wf-def-metric b { color: var(--text); font-weight: 600; }

.wf-inline-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-end;
  margin-block-start: 10px;
}

.wf-inline-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11.5px;
  color: var(--muted);
}

.wf-inline-form .ui-input, .wf-inline-form select { min-width: 150px; }

.wf-checkline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text);
}

/* ═══════════════════════════════════════════════════════════════════
   Workflow builder (M6 phase 4). Two columns: the step list you edit,
   and the graph + validation you read. On a narrow screen they stack,
   with the graph first — "what did I just build" beats "field 7 of 12".
   ═══════════════════════════════════════════════════════════════════ */
.wf-b-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px 14px;
  margin-block: 12px;
}

.wf-b-field { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--muted); }
.wf-b-field--wide { grid-column: 1 / -1; }
.wf-b-field .ui-hint { font-size: 10.5px; }

.wf-b-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

@media (max-width: 1100px) {
  .wf-b-layout { grid-template-columns: 1fr; }
  .wf-b-col--side { order: -1; }        /* the graph first when stacked */
}

.wf-b-col { min-width: 0; }

.wf-b-subhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-block: 14px 6px;
}

.wf-b-subhead h4, .wf-b-col--side h4 {
  margin: 0;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}

.wf-b-col--side h4 { margin-block: 14px 6px; }

/* ── inputs (params) ─────────────────────────────────────────────── */
.wf-b-params { display: flex; flex-direction: column; gap: 6px; }

.wf-b-param {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px auto auto;
  gap: 8px;
  align-items: center;
}

/* ── step cards ──────────────────────────────────────────────────── */
.wf-b-step {
  border: 1px solid var(--card-b);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 10px 12px;
  margin-block-end: 10px;
}

.wf-b-step.is-bad { border-color: var(--danger); }

/* A click on the graph scrolls to its card; the flash is what makes the
   two views feel like one thing. */
.wf-b-step.is-focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.wf-b-step-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.wf-b-step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  background: var(--surface-b);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  flex: none;
}

.wf-b-step-head .wf-b-id {
  max-width: 220px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}

.wf-b-step-head .wf-b-type { max-width: 190px; font-size: 12px; }
.wf-b-step-head .wf-actions { margin-inline-start: auto; display: flex; gap: 2px; }

.wf-b-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px 12px;
  margin-block-start: 10px;
}

.wf-b-area { font-size: 12px; resize: vertical; }

.wf-b-json {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
}

/* Unparseable JSON keeps its text — losing what someone typed is worse than
   showing it is wrong — and says which box is the problem. */
.wf-b-json.is-bad, .wf-b-raw.is-bad { border-color: var(--danger); }

.wf-b-raw {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
}

.wf-b-step-problems {
  margin: 8px 0 0;
  padding-inline-start: 18px;
  font-size: 11.5px;
  color: var(--muted);
}

.wf-b-step-problems li.is-err { color: var(--danger); }

/* ── validation panel ────────────────────────────────────────────── */
.wf-b-problems { margin-block-start: 10px; }

.wf-b-warnings {
  margin-block-start: 8px;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
  font-size: 11.5px;
  color: var(--text);
}

.wf-b-warnings ul, .wf-b-problems ul { margin: 6px 0 0; padding-inline-start: 18px; }

/* The shared .ui-input gives textareas a generous min-height that suits a message
   composer and dwarfs a two-line field. Constrain the builder's own boxes. */
#wfBuilderDesc { min-height: 52px; height: 52px; resize: vertical; }
.wf-b-area { min-height: 44px; height: 44px; }
.wf-b-json { min-height: 44px; height: 52px; }
.wf-b-raw { min-height: 320px; height: 380px; }

/* ═══════════════════════════════════════════════════════════════════
   Builder · templates, translations, dry run  (M6 phase 8)
   ═══════════════════════════════════════════════════════════════════ */

.wf-b-modes { margin-block: 10px 4px; }
.wf-b-pane { margin-block-start: 12px; }
.wf-b-field--inline { flex-direction: row; align-items: center; gap: 8px; }

/* Template gallery: cards, because the description is what a person picks on. */
.wf-tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  margin-block-start: 10px;
}

.wf-tpl-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--card-b);
  border-radius: var(--radius-md, 8px);
  background: var(--card-bg, var(--surface-b));
}

.wf-tpl-card b { font-size: 13px; }
.wf-tpl-card p { margin: 0; }
.wf-tpl-card.is-bad { border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.wf-tpl-card button { margin-block-start: auto; }

/* Translations: a two-column diff. English on one side, the translation on the
   other, one row per field a person reads — the only layout in which "what is
   still missing" is answerable at a glance. */
.wf-b-i18n { display: flex; flex-direction: column; gap: 8px; }

.wf-b-i18n-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px 14px;
  padding-block-end: 8px;
  border-block-end: 1px solid var(--card-b);
}

@media (max-width: 780px) {
  .wf-b-i18n-row { grid-template-columns: 1fr; }
}

.wf-b-i18n-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

.wf-b-i18n-base {
  margin: 0;
  font-size: 12px;
  color: var(--text);
  overflow-wrap: anywhere;
  padding: 6px 8px;
  border-radius: 6px;
  background: var(--surface-b);
}

/* Dry run: a numbered walk, with the assumptions visibly flagged. A preview that
   hides which parts it guessed is worse than no preview. */
.wf-b-dry-form { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; }
.wf-b-dry-form .wf-b-field { min-width: 160px; }

.wf-b-dry-scope {
  margin-block: 12px 6px;
  padding: 8px 10px;
  border-radius: 6px;
  background: var(--surface-b);
  font-size: 12px;
}

.wf-b-dry-steps { margin: 8px 0 0; padding-inline-start: 22px; font-size: 12px; }
.wf-b-dry-steps li { margin-block: 6px; }
.wf-b-dry-steps li.is-err { color: var(--danger); }
.wf-b-dry-steps code { font-size: 11.5px; }
.wf-b-dry-steps > li > div { color: var(--muted); }

/* Admin · trigger rows */
.wf-trig-runs { flex-basis: 100%; }
.wf-trig-run-list { margin: 4px 0 0; padding-inline-start: 18px; font-size: 11.5px; color: var(--muted); }

/* ═══════════════════════════════════════════════════════════════════
   Builder · editable canvas  (P2, 2026-09-14)
   The drawing is the shared SVG renderer; these are the interaction
   targets laid over it, so pointer, focus and keyboard behaviour are
   HTML's rather than something re-implemented on SVG nodes.
   ═══════════════════════════════════════════════════════════════════ */

.wf-canvas-host { min-height: 240px; }
.wf-canvas-surface { display: flex; flex-direction: column; gap: 10px; }

/* The drawing and its overlay share one positioned box, so a node handle can
   be placed at exactly the coordinates the layout produced. */
.wf-canvas-drawing {
  position: relative;
  overflow: auto;
  padding: 4px;
  border: 1px solid var(--card-b);
  border-radius: var(--radius-md, 8px);
  background: var(--surface-b);
}

.wf-canvas-overlay { position: absolute; inset-block-start: 4px; inset-inline-start: 4px; }

.wf-canvas-node {
  position: absolute;
  border-radius: 10px;
  border: 2px solid transparent;
  cursor: grab;
  touch-action: none;          /* the pointer drag owns the gesture */
}

.wf-canvas-node:hover { border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.wf-canvas-node:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wf-canvas-node.is-selected { border-color: var(--accent); }
.wf-canvas-node.is-drop {
  border-color: var(--ok);
  background: color-mix(in srgb, var(--ok) 12%, transparent);
}
/* A step nothing reaches is a real defect the validator reports; show it on the
   node too, where somebody is looking when they cause it. */
.wf-canvas-node.is-unreachable { border-color: var(--warn); border-style: dashed; }

.is-dragging .wf-canvas-node { cursor: grabbing; }

/* The connection handle exists only on steps whose type can carry an edge, so
   the canvas cannot draw something the engine has no way to express. */
.wf-canvas-port {
  position: absolute;
  inset-block-end: -7px;
  inset-inline-start: calc(50% - 7px);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--surface-b);
  cursor: crosshair;
}

.wf-canvas-palette {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px 12px;
}

.wf-canvas-palette .ui-hint { flex-basis: 100%; }
