/*!
 * Process Graph 0.4.2 · Atelier (Process 51)
 * Three layers on one stage, all of them using the same percent coordinates: the hairlines
 * in a stretched SVG, the dots and the labels as elements above it. Colours, motion and
 * type come from custom properties only: each one reads a token of components/tokens with a
 * neutral system fallback, so the component works on a page with the tokens, on a page of
 * another design language that sets the --process-graph-* properties itself, and on a page
 * with neither.
 *
 * Rules below "Process map" style the second, additive rendering path added in 0.2.0 (a
 * process-graph--map root): symbols, directed and shaped edges, a decision diamond, a step
 * box and a platform surface, all drawn in one real SVG rather than the stretched lines-only
 * SVG above. Since 0.3.0 the same path draws sheets, one per party, with hard shadows and a
 * dashed edge for a party outside the company. The two paths never apply to the same root at
 * once (see process-graph.ts, isStationVariant), so nothing here changes how the original
 * dots-and-hairlines format looks.
 */

/* Defaults without specificity, so any page can override them without a fight. */
:where(.process-graph) {
  /* Colour roles of the layout data, bound to the tokens, with a neutral fallback.
     `accent` is the one highlight of the host's design language (0.3.0, formerly blue). */
  --process-graph-ink: var(--ink, CanvasText);
  --process-graph-ink-2: var(--ink-2, GrayText);
  --process-graph-accent: var(--blue, CanvasText);
  --process-graph-red: var(--red, CanvasText);

  /* A band under an accent edge, like a highlighter on a plan. Off unless a page sets it. */
  --process-graph-accent-band: transparent;
  --process-graph-accent-band-width: 8px;

  --process-graph-line-color: var(--ink, CanvasText);
  --process-graph-line-width: var(--hairline-width, 1px);
  --process-graph-label-color: var(--ink-2, GrayText);
  --process-graph-label-size: var(--font-size-label-web, 14px);
  --process-graph-label-font: var(--font-sans, system-ui, sans-serif);
  --process-graph-label-weight: var(--font-weight-text, 400);

  /* A state switch is a CSS transition; an interpolated frame switches it off. */
  --process-graph-duration: var(--motion-duration, 0s);
  --process-graph-ease: var(--motion-ease, ease);

  /* Aspect ratio of the stage. The script sets the value from the layout data. */
  --process-graph-aspect: 16 / 9;

  /* Measured stage size in pixels, written once per resize by the script. */
  --process-graph-width: 0px;
  --process-graph-height: 0px;

  /* Process map (0.3.0): the sheet a party's part of the process lies on, its outline, the
     dash of a party outside the company, the hard shadow of a lifted sheet and the fill of
     a frame such as "Eine Anwendung". */
  --process-graph-sheet: var(--bg, Canvas);
  --process-graph-sheet-line: var(--hairline, GrayText);
  --process-graph-external-dash: 5 4;
  --process-graph-shadow: var(--process-graph-shadow-light);
  --process-graph-frame: var(--process-graph-surface);

  /* The shadow's default per mode (0.4.1). A shadow stays darker than the ground in both
     modes: ink mixed into transparent darkens a light ground, but on a dark ground the ink
     is light, so dark mode takes its own value (see the rules after this block). A page
     that sets --process-graph-shadow itself decides for both modes. */
  --process-graph-shadow-light: color-mix(in srgb, var(--process-graph-ink) 8%, transparent);
  --process-graph-shadow-dark: rgba(0, 0, 0, 0.55);

  /* Process map only (0.2.0): the fill behind a symbol, a step box, a decision diamond and
     a platform surface, so a shape reads on top of the edges that pass under or through it. */
  --process-graph-surface: var(--process-graph-sheet);

  /* Process map type (0.3.0): a step's word, a sheet's name, and a halo in the surface
     colour that keeps a word legible where a line passes under it (0 draws none). */
  --process-graph-step-font: var(--process-graph-label-font);
  --process-graph-step-weight: var(--font-weight-title, 600);
  --process-graph-plane-label-font: var(--process-graph-label-font);
  --process-graph-plane-label-size: calc(var(--process-graph-label-size) * 0.86);
  --process-graph-plane-label-weight: var(--font-weight-title, 600);
  --process-graph-plane-label-spacing: 0.12em;
  --process-graph-label-halo: 0px;

  /* How a sheet's name is set (0.4.1): capitals for the website; `none` keeps the spelling,
     as design language 1.1 asks for on customer pages. */
  --process-graph-plane-label-transform: uppercase;

  /* Process map lines (0.4.2): an edge is edge-width wide plus edge-width-per-weight for each
     unit of its weight, an arrowhead arrow-size long plus arrow-size-per-weight per unit, and
     arrowheads and a dead end's bar carry an outline of arrow-outline in their own colour. The
     script reads the lengths once per resize, so the words keep off lines as wide as drawn. */
  --process-graph-edge-width: 0.6px;
  --process-graph-edge-width-per-weight: 0.9px;
  --process-graph-arrow-size: 5px;
  --process-graph-arrow-size-per-weight: 3px;
  --process-graph-arrow-outline: 1px;

  /* Written by the script: how far the camera scales the words (1 with fixed labels), and since
     0.4.2 once more per role, which may keep a floor (ProcessGraphOptions.labelScaleFloor). */
  --process-graph-label-scale: 1;
}

:where(.process-graph--mobile) {
  --process-graph-label-size: var(--font-size-label-app, 12px);
}

/* Dark mode, following the same switch as components/tokens: the system setting unless the
   page forces a mode with data-theme on <html>. Still without specificity. */
@media (prefers-color-scheme: dark) {
  :where(:root:not([data-theme="light"])) :where(.process-graph) {
    --process-graph-shadow: var(--process-graph-shadow-dark);
  }
}

:where(:root[data-theme="dark"]) :where(.process-graph) {
  --process-graph-shadow: var(--process-graph-shadow-dark);
}

:where(.process-graph) {
  position: relative;
  aspect-ratio: var(--process-graph-aspect);
  width: 100%;
}

.process-graph__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--process-graph-line-color);
  stroke-width: var(--process-graph-line-width);
  overflow: visible;
}

/* The stroke width stays a hairline although the SVG is stretched. */
.process-graph__line {
  vector-effect: non-scaling-stroke;
  transition: stroke-opacity var(--process-graph-duration) var(--process-graph-ease);
}

/*
 * A dot is an element, not an SVG circle: in the stretched SVG a circle would be an ellipse.
 * Its base size is one percent of the stage height, the layout data scales it from there,
 * so only transform and opacity change while it moves. The transform itself is written by
 * the script as a whole value, because a transition of a property composed from custom
 * properties does not run reliably.
 */
.process-graph__dot {
  position: absolute;
  left: 0;
  top: 0;
  height: calc(var(--process-graph-height) / 100);
  aspect-ratio: 1;
  border-radius: 50%;
  background: currentColor;
  color: var(--process-graph-ink);
  transform: translate(-50%, -50%);
  transition:
    transform var(--process-graph-duration) var(--process-graph-ease),
    opacity var(--process-graph-duration) var(--process-graph-ease),
    color var(--process-graph-duration) var(--process-graph-ease);
  will-change: transform;
}

/* A label is real text, for the same reason: in the stretched SVG it would be distorted.
   Its horizontal anchor rides in the transform, so the alignment can travel without a jump. */
.process-graph__label {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  font-family: var(--process-graph-label-font);
  font-size: var(--process-graph-label-size);
  font-weight: var(--process-graph-label-weight);
  line-height: 1;
  color: var(--process-graph-label-color);
  transform: translate(-50%, -50%);
  transition:
    transform var(--process-graph-duration) var(--process-graph-ease),
    opacity var(--process-graph-duration) var(--process-graph-ease);
}

/* While a caller writes a frame per scroll position, it is the clock: no transition may lag.
   is-still is the same for one frame, when only the stage size has changed. */
.process-graph.is-interpolating .process-graph__dot,
.process-graph.is-interpolating .process-graph__label,
.process-graph.is-interpolating .process-graph__line,
.process-graph.is-still .process-graph__dot,
.process-graph.is-still .process-graph__label,
.process-graph.is-still .process-graph__line,
.process-graph.is-interpolating .process-graph__map-node,
.process-graph.is-interpolating .process-graph__map-edge,
.process-graph.is-interpolating .process-graph__map-band,
.process-graph.is-interpolating .process-graph__map-head,
.process-graph.is-interpolating .process-graph__map-node-label,
.process-graph.is-interpolating .process-graph__map-edge-label,
.process-graph.is-interpolating .process-graph__map-note,
.process-graph.is-still .process-graph__map-node,
.process-graph.is-still .process-graph__map-edge,
.process-graph.is-still .process-graph__map-band,
.process-graph.is-still .process-graph__map-head,
.process-graph.is-still .process-graph__map-node-label,
.process-graph.is-still .process-graph__map-edge-label,
.process-graph.is-still .process-graph__map-note {
  transition: none;
}

/* "Reduce motion": the same states, no transition between them. */
@media (prefers-reduced-motion: reduce) {
  .process-graph__dot,
  .process-graph__label,
  .process-graph__line,
  .process-graph__map-node,
  .process-graph__map-edge,
  .process-graph__map-band,
  .process-graph__map-head,
  .process-graph__map-node-label,
  .process-graph__map-edge-label,
  .process-graph__map-note {
    transition: none;
  }
}

/* ------------------------------------------------------------------ *
 * Process map (0.2.0): symbols, directed and shaped edges, branching
 * ------------------------------------------------------------------ */

.process-graph__map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* A decision, a step box and the platform surface stand on the label colour by default; a
   symbol node and a plain dot inside a map take the ink colour. The script overrides this
   per node with the role the data names (colorToCss), this is only the value before a
   colour has been resolved for the very first paint. */
.process-graph__map-shape,
.process-graph__map-symbol {
  color: var(--process-graph-ink);
}

.process-graph__map-node {
  transition:
    transform var(--process-graph-duration) var(--process-graph-ease),
    opacity var(--process-graph-duration) var(--process-graph-ease),
    color var(--process-graph-duration) var(--process-graph-ease);
}

.process-graph__map-shape {
  fill: var(--process-graph-surface);
  stroke: currentColor;
  stroke-width: 1.5px;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.process-graph__map-node--platform .process-graph__map-shape {
  fill: var(--process-graph-frame);
}

.process-graph__map-symbol {
  stroke-width: 1.4px;
}

.process-graph__map-edge {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition:
    d var(--process-graph-duration) var(--process-graph-ease),
    stroke-opacity var(--process-graph-duration) var(--process-graph-ease),
    stroke var(--process-graph-duration) var(--process-graph-ease);
}

.process-graph__map-band {
  fill: none;
  stroke: var(--process-graph-accent-band);
  stroke-width: var(--process-graph-accent-band-width);
  stroke-linecap: round;
  stroke-linejoin: round;
  transition:
    d var(--process-graph-duration) var(--process-graph-ease),
    opacity var(--process-graph-duration) var(--process-graph-ease);
}

/* The script writes fill and stroke in the edge's colour; the outline is what makes a dead
   end's bar, a path without area, visible at all. */
.process-graph__map-head {
  stroke-width: var(--process-graph-arrow-outline);
  stroke-linejoin: round;
  stroke-linecap: round;
  transition: opacity var(--process-graph-duration) var(--process-graph-ease);
}

.process-graph__map-node-label,
.process-graph__map-edge-label,
.process-graph__map-note {
  font-family: var(--process-graph-label-font);
  font-size: calc(var(--process-graph-label-size) * var(--process-graph-node-label-scale, var(--process-graph-label-scale)));
  font-weight: var(--process-graph-label-weight);
  dominant-baseline: middle;
  paint-order: stroke;
  stroke: var(--process-graph-surface);
  stroke-width: var(--process-graph-label-halo);
  stroke-linejoin: round;
  transition:
    opacity var(--process-graph-duration) var(--process-graph-ease),
    x var(--process-graph-duration) var(--process-graph-ease),
    y var(--process-graph-duration) var(--process-graph-ease);
}

.process-graph__map-node-label {
  fill: var(--process-graph-ink);
}

/* A step's word sits inside its box, which already masks the lines: no halo needed. */
.process-graph__map-step-label {
  font-size: calc(var(--process-graph-label-size) * var(--process-graph-step-label-scale, var(--process-graph-label-scale)));
  font-family: var(--process-graph-step-font);
  font-weight: var(--process-graph-step-weight);
  stroke-width: 0;
}

.process-graph__map-edge-label,
.process-graph__map-note {
  fill: var(--process-graph-label-color);
}

.process-graph__map-edge-label {
  font-size: calc(var(--process-graph-label-size) * var(--process-graph-edge-label-scale, var(--process-graph-label-scale)));
}

.process-graph__map-note {
  font-size: calc(var(--process-graph-label-size) * var(--process-graph-note-label-scale, var(--process-graph-label-scale)));
}

/* ------------------------------------------------------------------ *
 * Sheets (0.3.0): one per party, lifted by the camera's spread
 * ------------------------------------------------------------------ */

.process-graph__map-sheet,
.process-graph__map-ground {
  fill: var(--process-graph-sheet);
  stroke: var(--process-graph-sheet-line);
  stroke-width: 1px;
  stroke-linejoin: round;
}

/* A party outside the company: the sheet's edge is dashed. */
.process-graph__map-sheet--external {
  stroke-dasharray: var(--process-graph-external-dash);
}

/* Shadows are hard, offset areas, never a blur or a filter. */
.process-graph__map-floor-shadow,
.process-graph__map-shadow {
  fill: var(--process-graph-shadow);
  stroke: none;
}

.process-graph__map-plane-icon {
  color: var(--process-graph-ink-2);
  stroke-width: 1.6px;
}

.process-graph__map-plane-name {
  font-family: var(--process-graph-plane-label-font);
  font-size: calc(var(--process-graph-plane-label-size) * var(--process-graph-plane-label-scale, var(--process-graph-label-scale)));
  font-weight: var(--process-graph-plane-label-weight);
  letter-spacing: var(--process-graph-plane-label-spacing);
  text-transform: var(--process-graph-plane-label-transform);
  dominant-baseline: middle;
  fill: var(--process-graph-ink-2);
}
