/* ============================================================
   DIAGRAMS.CSS — the case diagrams in HTML
   Rebuilt from the original SVGs (img/helpdesk/*.svg), token for token.

   How it scales: every diagram keeps its SVG drawing size (1600 wide).
   --u is one SVG pixel at the current width (100cqi / 1600), so every
   size below is written in SVG pixels × --u and the diagram scales
   exactly like the image did, text included.

   Cards, text and pills are HTML. Connectors, dots and arrowheads stay
   inline SVG (.dg-wires) in the diagram's own coordinates, under the
   cards. Icons are inline SVG inside the HTML.

   Layout of a diagram:
     div.dg[style="--dg-h: <height>; --dg-oy: <viewBox y>"]
       > svg.dg-wires (viewBox = the original viewBox)
       > .dg-at[style="--x; --y; --w; --h"] boxes placed from the SVG
         coordinates; their content is laid out with flex and padding.
   ============================================================ */

@property --u {
  syntax: "<length>";
  inherits: true;
  initial-value: 1px;
}

/* Box coordinates never inherit: an unset --h means height: auto */
@property --x { syntax: "*"; inherits: false; }
@property --y { syntax: "*"; inherits: false; }
@property --w { syntax: "*"; inherits: false; }
@property --h { syntax: "*"; inherits: false; }

.dg-frame {
  container-type: inline-size;
}

.dg {
  /* ---------- Color ---------- */
  --color-bg: #fbfaf8; /* canvas */
  --color-surface: #ffffff; /* cards, fields */
  --color-surface-sunken: #f6f4f0; /* table header */
  --color-shadow: #eeebe5; /* solid offset shadow */
  --color-ink: #2b2b2b; /* main text, chips, button */
  --color-text-muted: #8a8780; /* secondary, headers, check */
  --color-text-caption: #5a574f; /* "Step 1" (repeticion-datos only) */
  --color-text-edge: #555555; /* connector pill text */
  --color-icon: #6f6c66;
  --color-border: #e2dfd9; /* cards, dividers */
  --color-border-field: #cfcac2; /* form fields */
  --color-border-edge: #d6d2cb; /* connector pill */
  --color-connector: #a8a49d; /* flow lines */
  --color-connector-dot: #7d7a74; /* origin dot and arrowhead */
  --color-rule-text: #1f6fb5; /* rules, states, totals */
  --color-rule-fill: #eef5fc;
  --color-rule-border: #b9d8f2; /* also the 2px underline */

  /* ---------- Type ---------- */
  --font-mono: "JetBrains Mono", "IBM Plex Mono", "SF Mono", Menlo, Consolas,
    "DejaVu Sans Mono", monospace;

  /* ---------- Radii ---------- */
  --radius-container: 14; /* screen, modules */
  --radius-card-lg: 12; /* ticket, appointment schedules */
  --radius-card: 10; /* blocks, sources, steps */
  --radius-table: 8; /* table, button */
  --radius-field: 6; /* fields, number chip, connector pill */
  --radius-pill: 11; /* rule pill (= height / 2) */

  /* ---------- Borders and strokes ---------- */
  --border-card: 1px; /* 1.2 in the SVG: 1px avoids 1↔2px jumps */
  --border-thin: 1px;

  /* ---------- Shadow (solid, no blur) ---------- */
  --shadow-card: 0 calc(3 * var(--u)) 0 0 var(--color-shadow);

  --u: calc(100cqi / 1600);
  position: relative;
  width: 100%;
  aspect-ratio: 1600 / var(--dg-h);
  overflow: hidden;
  background: var(--color-bg);
  font-family: var(--font-mono);
  color: var(--color-ink);
  font-size: calc(13 * var(--u));
  line-height: 1;
  font-synthesis: none;
}

.dg *,
.dg *::before,
.dg *::after {
  box-sizing: border-box;
  margin: 0;
}

/* Box placed from SVG coordinates (all in SVG px) */
.dg-at {
  position: absolute;
  z-index: 1;
  left: calc(var(--x) * var(--u));
  top: calc((var(--y) - var(--dg-oy)) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
}

/* Centered on --x (pills on connectors, edge labels) */
.dg-at--cx {
  z-index: 3; /* pills and labels sit on top of their connector */
  transform: translateX(-50%);
}

/* Connectors: the original paths, drawn over the cards as in the SVGs
   (in fuentes-a-layout the arrows run into the record screen) */
.dg-wires {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.dg-ico {
  display: block;
  flex: none;
  overflow: visible;
}

/* ---------- Surfaces ---------- */
.dg-card {
  /* The border is an inset shadow: it takes no space, so content sits
     exactly where the SVG put it */
  --dg-edge: inset 0 0 0 var(--border-card) var(--color-border);
  display: flex;
  flex-direction: column;
  border-radius: calc(var(--radius-card) * var(--u));
  background: var(--color-surface);
  box-shadow: var(--dg-edge), var(--shadow-card);
}

.dg-card--flat {
  box-shadow: var(--dg-edge);
}

.dg-card--lg {
  border-radius: calc(var(--radius-card-lg) * var(--u));
}

.dg-card--container {
  border-radius: calc(var(--radius-container) * var(--u));
}

/* ---------- Text styles (size / weight / tracking in SVG px) ---------- */
.dg-module-title,
.dg-block-title,
.dg-node-title,
.dg-ticket-title,
.dg-node-kind,
.dg-ticket-kind,
.dg-table-head,
.dg-button {
  text-transform: uppercase;
}

.dg-module-title {
  font-size: calc(16 * var(--u));
  font-weight: 700;
  letter-spacing: calc(0.4 * var(--u));
}

.dg-block-title {
  font-size: calc(14 * var(--u));
  font-weight: 700;
  letter-spacing: calc(0.4 * var(--u));
}

.dg-node-title {
  font-size: calc(13 * var(--u));
  font-weight: 600;
  letter-spacing: calc(0.4 * var(--u));
}

.dg-ticket-title {
  font-size: calc(13 * var(--u));
  font-weight: 700;
  letter-spacing: calc(0.4 * var(--u));
}

.dg-node-kind {
  font-size: calc(12 * var(--u));
  letter-spacing: calc(0.4 * var(--u));
  color: var(--color-text-muted);
}

.dg-ticket-kind {
  font-size: calc(11 * var(--u));
  letter-spacing: calc(0.4 * var(--u));
  color: var(--color-text-muted);
}

.dg-step-name {
  font-size: calc(13 * var(--u));
  font-weight: 600;
  line-height: calc(19 * var(--u));
}

.dg-body {
  font-size: calc(13 * var(--u));
}

.dg-edge-label {
  font-size: calc(13 * var(--u));
  font-weight: 700;
  white-space: nowrap;
}

.dg-description {
  font-size: calc(12 * var(--u));
  line-height: calc(20 * var(--u));
  color: var(--color-text-muted);
}

.dg-table-head {
  font-size: calc(11 * var(--u));
  font-weight: 600;
  letter-spacing: calc(0.8 * var(--u));
  color: var(--color-text-muted);
}

.dg-table-cell {
  font-size: calc(12 * var(--u));
}

.dg-summary {
  font-size: calc(13 * var(--u));
  color: var(--color-text-muted);
  white-space: nowrap;
}

.dg-muted {
  color: var(--color-text-muted);
}

/* ---------- Pills ---------- */
/* Rule pill: a state or a rule. Two variants, as in the originals:
   sentence case 12/600/0 and caps 11/600/0.3 (recorrido-legacy). */
.dg-pill {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: calc(4 * var(--u));
  height: calc(22 * var(--u));
  padding: 0 calc(10 * var(--u));
  border: var(--border-thin) solid var(--color-rule-border);
  border-radius: calc(var(--radius-pill) * var(--u));
  background: var(--color-rule-fill);
  font-size: calc(12 * var(--u));
  font-weight: 600;
  white-space: nowrap;
  color: var(--color-rule-text);
}

.dg-pill--caps {
  padding-right: calc(18 * var(--u)); /* as drawn in recorrido-legacy */
  font-size: calc(11 * var(--u));
  letter-spacing: calc(0.3 * var(--u));
  text-transform: uppercase;
}

.dg-pill .dg-ico {
  width: calc(12 * var(--u));
  height: calc(12 * var(--u));
}

/* Connector pill: the cardinality or verb on a line */
.dg-edge-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: calc(56 * var(--u));
  height: calc(20 * var(--u));
  padding: 0 calc(8 * var(--u));
  border: var(--border-thin) solid var(--color-border-edge);
  border-radius: calc(var(--radius-field) * var(--u));
  background: var(--color-surface);
  font-size: calc(11 * var(--u));
  letter-spacing: calc(0.2 * var(--u));
  white-space: nowrap;
  color: var(--color-text-edge);
}

.dg-edge-pill--plain {
  letter-spacing: 0;
}

/* ---------- Recorrido legacy: ticket and steps ---------- */
.dg-ticket__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  height: calc(50 * var(--u));
  padding: calc(20.8 * var(--u)) calc(20 * var(--u)) 0;
  border-bottom: var(--border-card) solid var(--color-border);
}

.dg-ticket__rows {
  display: flex;
  flex-direction: column;
  padding: calc(8 * var(--u)) calc(20 * var(--u)) 0;
}

.dg-ticket__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: calc(36 * var(--u));
  /* dashed divider: 4 on, 4 off, 1px */
  background: linear-gradient(
      to right,
      var(--color-border) 50%,
      transparent 50%
    )
    left bottom / calc(8 * var(--u)) var(--border-thin) repeat-x;
}

.dg-ticket__row:last-child {
  background: none;
}

.dg-ticket__row .dg-ico {
  width: calc(15 * var(--u));
  height: calc(16 * var(--u));
  margin-right: calc(-1 * var(--u));
  transform: translateY(calc(-2 * var(--u)));
}

.dg-step {
  display: flex;
  flex-direction: column;
}

.dg-step .dg-card {
  height: calc(106 * var(--u));
  padding: calc(18 * var(--u)) calc(21 * var(--u)) 0 calc(18 * var(--u));
}

.dg-step__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.dg-chip {
  display: grid;
  place-items: center;
  width: calc(24 * var(--u));
  height: calc(24 * var(--u));
  border-radius: calc(var(--radius-field) * var(--u));
  background: var(--color-ink);
  font-size: calc(13 * var(--u));
  font-weight: 700;
  color: #fff;
}

.dg-step__head .dg-ico {
  width: calc(18 * var(--u));
  height: calc(18 * var(--u));
}

.dg-step .dg-step-name {
  margin-top: calc(13.8 * var(--u));
}

.dg-step__table {
  margin-top: calc(17.7 * var(--u));
  padding-left: calc(18 * var(--u));
  white-space: nowrap;
}

/* 2px underline in the rule border colour: step 2's screen, where the
   loop from step 6 brings the work back and the flow ends */
.dg-step__table--repeat span {
  text-decoration: underline;
  text-decoration-color: var(--color-rule-border);
  text-decoration-thickness: calc(2 * var(--u));
  text-underline-offset: calc(7 * var(--u));
}

/* ---------- Fuentes a layout: sources, screen, blocks, table ---------- */
.dg-source {
  flex-direction: row;
  align-items: flex-start;
  gap: calc(16 * var(--u));
  padding: 0 calc(24 * var(--u));
}

.dg-source .dg-ico {
  width: calc(16 * var(--u));
  height: calc(18 * var(--u));
  margin-top: calc(15.4 * var(--u));
}

.dg-source__text {
  display: flex;
  flex-direction: column;
  gap: calc(9.9 * var(--u));
  padding-top: calc(18.8 * var(--u));
  white-space: nowrap;
}

.dg-screen__head {
  height: calc(42 * var(--u));
  padding: calc(16.7 * var(--u)) calc(24 * var(--u)) 0;
  border-bottom: var(--border-card) solid var(--color-border);
  font-size: calc(12 * var(--u));
  color: var(--color-text-muted);
}

.dg-block {
  padding: calc(22 * var(--u)) calc(20 * var(--u)) calc(20 * var(--u));
}

.dg-block .dg-description {
  margin-top: calc(11.7 * var(--u));
}

.dg-block .dg-pill {
  margin-top: auto;
  padding-right: calc(18 * var(--u)); /* as drawn in fuentes-a-layout */
}

.dg-block__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

.dg-block__head .dg-block-title {
  margin-top: calc(4 * var(--u));
}

.dg-block--workplaces {
  padding-top: calc(18 * var(--u));
}

.dg-block--workplaces .dg-description {
  margin-top: calc(1.7 * var(--u));
  line-height: 1;
}

.dg-block--workplaces .dg-pill {
  margin-top: calc(14.3 * var(--u));
}

.dg-button {
  display: grid;
  place-items: center;
  width: calc(144 * var(--u));
  height: calc(30 * var(--u));
  border-radius: calc(var(--radius-table) * var(--u));
  background: var(--color-ink);
  font-size: calc(11 * var(--u));
  font-weight: 600;
  letter-spacing: calc(0.3 * var(--u));
  white-space: nowrap;
  color: #fff;
}

.dg-table {
  display: grid;
  grid-template-columns:
    calc(300 * var(--u)) calc(220 * var(--u)) calc(216 * var(--u))
    1fr;
  margin-top: calc(20 * var(--u));
  overflow: hidden;
  border: var(--border-card) solid var(--color-border);
  border-radius: calc(var(--radius-table) * var(--u));
}

.dg-table > * {
  display: flex;
  align-items: center;
  height: calc(42 * var(--u));
  padding-left: calc(16 * var(--u));
  white-space: nowrap;
  border-top: var(--border-thin) solid var(--color-border);
}

.dg-table > .dg-table-head {
  height: calc(29 * var(--u));
  padding-top: calc(1.5 * var(--u));
  border-top: 0;
  border-bottom: var(--border-card) solid var(--color-border);
  background: var(--color-surface-sunken);
}

.dg-table > :nth-child(-n + 8) {
  border-top: 0;
}

.dg-table > .dg-table__action {
  justify-content: center;
  padding-left: 0;
  border-left: var(--border-thin) solid var(--color-border);
}

.dg-table__action .dg-ico {
  width: calc(16 * var(--u));
  height: calc(16 * var(--u));
}

/* ---------- Sincronizacion: modules ---------- */
.dg-module {
  padding: calc(27 * var(--u)) calc(26 * var(--u)) 0;
}

.dg-module__head {
  display: flex;
  align-items: center;
  gap: calc(13 * var(--u));
  height: calc(18 * var(--u));
  margin-left: calc(1 * var(--u));
}

.dg-module__head .dg-ico,
.dg-schedule__head .dg-ico {
  width: calc(18 * var(--u));
  height: calc(18 * var(--u));
}

.dg-module .dg-pill {
  margin-top: calc(17 * var(--u));
}

.dg-module__items {
  display: flex;
  flex-direction: column;
  gap: calc(16 * var(--u));
  margin-top: calc(26 * var(--u));
}

.dg-item {
  flex-direction: row;
  align-items: center;
  gap: calc(14 * var(--u));
  height: calc(60 * var(--u));
  padding-left: calc(18 * var(--u));
  white-space: nowrap;
}

.dg-item .dg-ico {
  width: calc(20 * var(--u));
  height: calc(20 * var(--u));
}

.dg-schedule {
  padding: calc(23 * var(--u)) calc(26 * var(--u)) 0;
}

.dg-schedule__head {
  display: flex;
  align-items: center;
  gap: calc(13 * var(--u));
  height: calc(18 * var(--u));
  margin-left: calc(1 * var(--u));
}

.dg-schedule .dg-pill {
  margin-top: calc(15 * var(--u));
}

/* ---------- Flow animation ----------
   A short ink pulse runs along each connector, one after another, in the
   order the work happened: ticket → steps 1–6 → back to step 2; the
   three sources into the record; the copy, then the read.
   Each pulse is a copy of its connector (.dg-pulse, pathLength 1) with a
   single dash that travels from start to end. One 16s cycle for every
   diagram; --i sets the turn (1.5s apart), --dash the pulse length as
   a share of the connector. Plays twice once the diagram reaches the
   middle of the screen (.is-playing, set by the page script), then rests; it plays
   again the next time the diagram scrolls into view. Never with
   reduced motion.
   stroke-dashoffset is not transform/opacity, on purpose: a few thin
   strokes repaint cheaply and nothing else can move a dash on a path. */
.dg-pulse {
  fill: none;
  stroke: var(--color-ink);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: var(--dash, 0.3) 2;
  stroke-dashoffset: var(--dash, 0.3);
  opacity: 0;
}

.dg.is-playing .dg-pulse {
  animation: dg-pulse 16s 2;
  animation-delay: calc((var(--i) + var(--dg-lead, 0)) * 1.5s);
}

/* The ticket opens the flow: it lights first, the pulses follow one
   turn later */
.dg:has(.dg-card--ticket) {
  --dg-lead: 1;
}

.dg.is-playing .dg-pulse--long {
  animation-name: dg-pulse-long;
}

@keyframes dg-pulse {
  0% {
    stroke-dashoffset: var(--dash, 0.3);
    opacity: 0;
    animation-timing-function: cubic-bezier(0.45, 0, 0.25, 1);
  }
  1.5%,
  8% {
    opacity: 0.85;
  }
  9.5%,
  100% {
    stroke-dashoffset: -1;
    opacity: 0;
  }
}

/* Longer connectors (the loop back to step 2) travel for twice as long */
@keyframes dg-pulse-long {
  0% {
    stroke-dashoffset: var(--dash, 0.3);
    opacity: 0;
    animation-timing-function: cubic-bezier(0.45, 0, 0.25, 1);
  }
  2%,
  17% {
    opacity: 0.85;
  }
  19%,
  100% {
    stroke-dashoffset: -1;
    opacity: 0;
  }
}

/* Arrival: when a pulse reaches a step, the card's edge darkens for a
   moment, then fades back. Step 2 lights up twice: in order, and again
   when step 6 sends the work back to the same screen. */
.dg-step .dg-card {
  position: relative;
}

.dg-target::after,
.dg-card--ticket::after,
.dg-step .dg-card::before,
.dg-step .dg-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 calc(1.5 * var(--u)) var(--dg-ring, var(--color-ink));
  opacity: 0;
  pointer-events: none;
}

/* Steps: a soft grey ring. The ticket, where it all starts, in the pill
   blue. */
.dg-card--ticket,
.dg-target {
  --dg-ring: var(--color-rule-text);
  --dg-ring-peak: 0.5;
}

/* The other diagrams: the card each arrow reaches rings in blue as the
   pulse arrives (--dg-arrive, set in the markup) */
.dg.is-playing .dg-target::after {
  animation: dg-arrive 16s 2;
  animation-delay: var(--dg-arrive);
}

.dg.is-playing .dg-card--ticket::after,
.dg.is-playing .dg-step .dg-card::after,
.dg.is-playing .dg-step:nth-child(4) .dg-card::before {
  animation: dg-arrive 16s 2;
}

.dg.is-playing .dg-step:nth-child(3) .dg-card::after {
  animation-delay: 2.74s;
}

.dg.is-playing .dg-step:nth-child(4) .dg-card::after {
  animation-delay: 4.24s;
}

.dg.is-playing .dg-step:nth-child(5) .dg-card::after {
  animation-delay: 5.74s;
}

.dg.is-playing .dg-step:nth-child(6) .dg-card::after {
  animation-delay: 7.24s;
}

.dg.is-playing .dg-step:nth-child(7) .dg-card::after {
  animation-delay: 8.74s;
}

.dg.is-playing .dg-step:nth-child(8) .dg-card::after {
  animation-delay: 10.24s;
}

/* The loop back from step 6 arrives at step 2 */
.dg.is-playing .dg-step:nth-child(4) .dg-card::before {
  animation-delay: 13.4s;
}

/* Steps wait dimmed (only once the page script has armed the diagram,
   so without script they stay fully visible) and take full opacity as
   the pulse reaches each one. Arrival times match the rings above. */
@media (prefers-reduced-motion: no-preference) {
  /* Arrival time of each step (--dg-at), shared by card and label */
  .dg-step:nth-child(3) { --dg-at: 2.74s; }
  .dg-step:nth-child(4) { --dg-at: 4.24s; }
  .dg-step:nth-child(5) { --dg-at: 5.74s; }
  .dg-step:nth-child(6) { --dg-at: 7.24s; }
  .dg-step:nth-child(7) { --dg-at: 8.74s; }
  .dg-step:nth-child(8) { --dg-at: 10.24s; }

  /* The card waits faint; its table label waits a little stronger so it
     stays readable, and both reach full opacity together */
  .dg.is-armed .dg-step > .dg-card {
    opacity: 0.3;
  }

  .dg.is-armed .dg-step > .dg-step__table {
    opacity: 0.6;
  }

  .dg.is-playing .dg-step > .dg-card {
    animation: dg-step-on 600ms cubic-bezier(0.32, 0.72, 0, 1) var(--dg-at) both;
  }

  .dg.is-playing .dg-step > .dg-step__table {
    animation: dg-label-on 600ms cubic-bezier(0.32, 0.72, 0, 1) var(--dg-at) both;
  }

  /* Step 2's screen gets its underline only at the end, when the loop
     from step 6 lands on it again: the flow ends there */
  .dg.is-armed .dg-step__table--repeat span {
    text-decoration-color: transparent;
  }

  .dg.is-playing .dg-step__table--repeat span {
    animation: dg-underline-on 500ms cubic-bezier(0.32, 0.72, 0, 1) 13.8s both;
  }
}

/* The loop's label waits hidden and appears as the pulse coming back
   from step 6 passes under it (pulse starts at 10.5s, reaches the
   label's middle at about 11.7s), then stays */
@media (prefers-reduced-motion: no-preference) {
  .dg.is-armed .dg-loop-pill {
    opacity: 0;
  }

  .dg.is-playing .dg-loop-pill {
    animation: dg-label-show 400ms cubic-bezier(0.32, 0.72, 0, 1) 11.45s both;
  }
}

@keyframes dg-label-show {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes dg-step-on {
  from {
    opacity: 0.3;
  }
  to {
    opacity: 1;
  }
}

@keyframes dg-label-on {
  from {
    opacity: 0.6;
  }
  to {
    opacity: 1;
  }
}

@keyframes dg-underline-on {
  from {
    text-decoration-color: transparent;
  }
  to {
    text-decoration-color: var(--color-rule-border);
  }
}

@keyframes dg-arrive {
  0% {
    opacity: var(--dg-ring-peak, 0.28);
    animation-timing-function: ease-out;
  }
  9%,
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dg.is-playing .dg-pulse,
  .dg.is-playing .dg-target::after,
  .dg.is-playing .dg-card--ticket::after,
  .dg.is-playing .dg-step .dg-card::before,
  .dg.is-playing .dg-step .dg-card::after {
    animation: none;
  }
}

/* ---------- Zones and a boundary (decision 4: rebuilt vs legacy) ----------
   The rebuilt side carries the hatched ground (it's where the reader
   starts, left to right), the boundary is a dashed line; only the sync
   connector crosses it. */
.dg-zone {
  z-index: 0;
  background:
    repeating-linear-gradient(315deg, rgb(43 40 38 / 0.045) 0 1px, transparent 0 50%) 0 0 / calc(10 * var(--u)) calc(10 * var(--u));
}
.dg-boundary {
  z-index: 0;
  border-inline-start: calc(1.5 * var(--u)) dashed #b9b4ac;
}
.dg-zone-label {
  z-index: 2;
  margin: 0;
  font-size: calc(17 * var(--u));
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: calc(28 * var(--u));
  color: #4a4642;
}
