/* =========================================================================
   template-parts/sections/section-process.php
   Moved out of the partial's inline <style id="es-process-css"> on the owner's
   instruction, 10 Sep 2026. en_print_css() (inc/css-loader.php) prints this
   file's <link> where the <style> used to be, once per page, so every page
   that renders this section shares this one file.
   ========================================================================= */

/* The badge sits on the dashed connector and needs a ring in the section's
   own background to punch a hole in it. That colour is the one thing here
   that changes with `bg`, so it is bound once as a variable rather than
   repeated down the file. */
.es-proc {
  --es-proc-surface: var(--bg-surface);
  --es-proc-gap: var(--gap-fluid-md);
  --es-proc-badge: 56px;

  /* --es-proc-line is now the CHEVRON's colour. It kept its name because
     the badge ring and the connector still have to be described together,
     and renaming it would touch the wrap script below for no gain while
     that script is still on disk.

     The three that follow describe the dashed stroke that used to run
     badge to badge. Nothing in the printed output reads them any more: the
     in-row rule is gone and the wrap script that read the other two is
     never printed. They are kept beside the flag that would bring that
     script back, because the three of them only mean anything together. */
  --es-proc-line: var(--brand-300);
  --es-proc-line-w: 2px;
  --es-proc-dash: 9px;
  --es-proc-dash-gap: 7px;
}

/* Insurance for the wrap connector, which reaches past the grid's right
   edge. The script keeps it inside the viewport, so this should never have
   anything to catch; it is here so that a mid-resize frame or a zoom level
   that lands between two measurements can never produce a sideways scroll.

   `clip` rather than `hidden` so it creates no scroll container and leaves
   the vertical axis visible: the badges' surface rings and any seam card at
   a section join are unaffected. */
.es-proc { overflow-x: clip; }

/* Stacking context for the wrap SVG, which is a sibling of the grid rather
   than a child, so that it can paint across the whole run instead of being
   positioned inside one item. */
.es-proc__rows { position: relative; }

.es-proc__wrap {
  position: absolute;
  top: 0;
  left: 0;
  overflow: visible;
  pointer-events: none;
  color: var(--es-proc-line);
}

.es-proc.es-bg-gray { --es-proc-surface: var(--gray-50); }
.es-proc.es-bg-tint { --es-proc-surface: var(--brand-50); }

/* Author-controlled line breaks, suppressed below the width the copy was
   broken against. See the block comment at the top of this file. */
.es-proc br { display: none; }

@media (min-width: 992px) {
  .es-proc br { display: inline; }
}

/* ── Head ──────────────────────────────────────────────────
   Pill form of the section label, matching the hero eyebrow.
   brand-700 ink on the brand-50 chip clears AA at 12px, where
   brand-600 would not. */
.es-proc__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
  padding: var(--space-2) var(--space-5);
  border: 1px solid var(--brand-100);
  border-radius: var(--radius-full);
  background: var(--accent-subtle);
  color: var(--brand-700);
  font-family: var(--font-label);
  font-size: var(--fs-eyebrow);
  font-weight: var(--font-bold);
  letter-spacing: 1.8px;
  text-transform: uppercase;
}

/* The leading dot is gone, on the owner's instruction. The chip is the
   label alone now. */

/* ── Row ───────────────────────────────────────────────────
   One card per step. Stacks on a phone, pairs on a tablet, and
   opens to a full row only where every card still has a
   readable measure. */
.es-proc__grid {
  list-style: none;
  display: grid;
  gap: var(--es-proc-gap);
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
}

@media (min-width: 768px) {
  .es-proc__grid { grid-template-columns: repeat(2, 1fr); }
}

.es-proc__item {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* ── Number badge ──────────────────────────────────────────
   White at rest, filling with brand on hover. Only colours
   change. That rule outlived its original reason: the badge used
   to be threaded onto a dashed rule running the width of the row,
   so moving or scaling it would have pulled the number off the
   line. There is no line now, and the badges still hold a common
   baseline across the row, so a badge that grew or lifted on
   hover would break that alignment instead. Same constraint,
   different cause. Anything added here must be paint-only.

   20px at 800 weight is deliberate, not a styling accident.
   White on brand-500 measures 3.49:1, which clears AA for large
   text (>=18.66px bold) and fails it below that, so the hovered
   badge depends on this size. The resting state is brand-600 on
   white at 4.67:1 and is safe at any size. */
.es-proc__badge {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--es-proc-badge);
  height: var(--es-proc-badge);
  margin: 0 auto;
  border: 1px solid var(--brand-200);
  border-radius: 50%;
  background: var(--bg-surface);
  color: var(--brand-600);
  font-family: var(--font-label);
  /* --fs-card-title, not the legacy --text-lg. That token is a fixed 20px
     from the old rem scale and was the only reference to it left in any
     migrated partial, so the badge numeral was the one piece of display
     type on the page that did not scale down on a phone. */
  font-size: var(--fs-card-title);
  font-weight: var(--font-extrabold);
  letter-spacing: var(--tracking-normal);
  /* Ring in the section's own background. It was there to cut the dashed
     connector cleanly behind the badge instead of letting it run under the
     edge. With the line gone it has no rule to hide, but it still sets the
     badge off its ground, so it stays. */
  box-shadow: 0 0 0 5px var(--es-proc-surface), var(--shadow-sm);
  transition: background-color var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out),
              color var(--duration-normal) var(--ease-out);
}

.es-proc__item:hover .es-proc__badge {
  border-color: var(--brand-500);
  background: var(--brand-500);
  color: var(--text-inverse);
}

/* The badge carried a pin tail here, a CSS triangle bridging it to the card
   below. Removed on the owner's instruction: the step marker is the plain
   round badge now. The --es-proc-pin custom property that coloured it went
   with it, since this rule was its only consumer. */

/* ── Card ──────────────────────────────────────────────────
   Shadow and brand-border hover, and deliberately NO transform.
   Depth here is carried by the shadow alone: the chevron between
   two cards is positioned against the card's own midline, so a
   card that lifted on hover would leave the mark beside it
   pointing at a card that has moved. Anything added to this
   hover must be paint-only. */
.es-proc__card {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  margin-top: var(--space-3);
  padding: var(--space-6) var(--space-5);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  box-shadow: var(--shadow-sm);
  text-align: center;
  transition: box-shadow var(--duration-normal) var(--ease-out),
              border-color var(--duration-normal) var(--ease-out);
}

.es-proc__item:hover .es-proc__card {
  border-color: var(--brand-200);
}

.es-proc__card h3 {
  margin: 0 0 var(--space-3);
  color: var(--text-heading);
  font-size: var(--fs-card-title);
  font-weight: var(--font-extrabold);
  line-height: var(--lh-subhead);
  letter-spacing: var(--tracking-normal);
}

/* brand-600 rather than brand-500: at this size the lighter orange
   misses AA on the card surface. */
.es-proc__sub {
  margin: 0;
  color: var(--brand-600);
  font-size: var(--fs-body-sm);
  font-weight: var(--font-bold);
  line-height: var(--lh-subhead);
}

/* ── Duration ──────────────────────────────────────────────
   Fenced by a hairline top and bottom, so it reads as a fact
   about the step rather than as part of either paragraph. */
.es-proc__time {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: var(--space-5) 0 0;
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-body);
  font-size: var(--fs-body-sm);
  font-weight: var(--font-semibold);
}

.es-proc__time svg {
  flex-shrink: 0;
  width: 17px;
  height: 17px;
  color: var(--brand-500);
}

/* Only the paragraph grows, so the hairlines above it stay on the same
   line across the row even when one step runs longer than the others. */
.es-proc__text {
  flex: 1 1 auto;
  margin: var(--space-5) 0 0;
  color: var(--text-body);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body);
}

/* A step with no duration would otherwise open with a stray rule. */
.es-proc__card .es-proc__sub + .es-proc__text,
.es-proc__card h3 + .es-proc__text { margin-top: var(--space-4); }

/* ── Connectors ────────────────────────────────────────────
   One large chevron standing in the gap between two cards, on the
   owner's instruction. It replaces the dashed rule that used to
   run badge to badge, and the SVG path that used to carry that
   rule around a row wrap. Nothing draws a line here any more.

   The mark is the third wedge of the site's triple-chevron CTA
   glyph, drawn once instead of three times. Same path data, from
   en_icon( 'arrow-single' ), so the buttons and this cannot drift
   into two different chevrons.

   ── A step ends a row when it is last OR on the column count ──
   Both cases have to drop the mark, and this is the part that was
   hard-won with the old rule: dropping only `:last-child` was the
   original behaviour and it was correct while every call fitted
   one row, which was true of every caller when this partial was
   written. It breaks the moment a run wraps, because the last
   card of row one still drew its connector, which then pointed
   off the right edge of the grid at a badge that is really on the
   line below. The chevron would point at the same nothing, so the
   same pairs are restated here.

   So each breakpoint states a pair: switch the mark on for every
   item, then switch it off on that width's row-ends,
   `:nth-child(Nn)` and `:last-child`.

   ── Why the order of these blocks matters ────────────────────
   `.es-proc__grid--3 .es-proc__item .es-proc__link` and
   `.es-proc__item:nth-child(2n) .es-proc__link` both compute to
   (0,3,0), so the wider rule only overrides the two-up one by
   coming later in the file. Do not reorder these blocks.

   Hidden by default, so a stacked grid draws no connector at all.
   That is correct: a chevron pointing right, between two cards
   that are stacked vertically, points at nothing. */
.es-proc__link {
  position: absolute;

  /* BETWEEN THE NUMBERS.

     Horizontally: `100%` is the grid cell, so half a gap past it is the
     middle of the space between this card and the next. Each badge is
     centred over its card, so that is also the midpoint between the two
     badges (measured: 496px between 302 and 690 at 1440).

     Vertically: the badges' own centre line, `--es-proc-badge / 2`, so the
     mark points from 01 to 02 rather than from card to card. Owner's
     instruction, 14 Sep 2026. This reverses the earlier move to the card's
     midline, which sat the mark 230 to 290px below the numbers it
     sequences. Written from the badge variable, so it follows if the badge
     size moves. */
  top: calc(var(--es-proc-badge) / 2);
  left: calc(100% + var(--es-proc-gap) / 2);
  transform: translate(-50%, -50%);
  display: none;

  /* ── Circle arrow ──
     Owner's instruction, 14 Sep 2026 ("06 Circle Arrow" reference): a
     plain arrow on a filled tint circle, replacing the bare chevron.

     48px against the 56px badge, so the circle reads as the joint between
     two numbers rather than as a third number. It sits wholly above the
     cards: centred on the badge line at 28px, it spans 4px to 52px, and
     the card top is at 68px (badge plus --space-3). Horizontally it hangs
     past the grid gap into the empty band beside the badges, which is
     clear at every width it is drawn at.

     brand-500 ink, not the old brand-300 --es-proc-line: on a brand-50
     ground the lighter orange washes out. The mark is aria-hidden
     decoration, so it has no contrast floor, but it should still read. */
  --es-proc-link-size: var(--space-7);
  --es-proc-link-bg: var(--brand-50);
  align-items: center;
  justify-content: center;
  width: var(--es-proc-link-size);
  height: var(--es-proc-link-size);
  border-radius: var(--radius-full);
  background: var(--es-proc-link-bg);
  color: var(--brand-500);
  line-height: 0;
  /* Above the cards. It clears them at every width the mark is drawn at,
     so this guards the tightest gap and any future size change rather
     than a collision that exists today. */
  z-index: 2;
  pointer-events: none;
}

/* A tint section's ground is brand-50 already, so the circle steps up
   one shade or it disappears into the band. */
.es-proc.es-bg-tint .es-proc__link { --es-proc-link-bg: var(--brand-100); }

.es-proc__link svg { display: block; }

/* Two up. Unscoped, because every grid takes this arrangement at
   this width unless a wider rule below overrides it. A four-column
   run between 768 and 1199px is two-up and used to draw no
   connectors at all, since the old rule was scoped to `--2`.

   `flex` rather than `block` on every "on" rule below: the circle
   centres the arrow with flex alignment. */
@media (min-width: 768px) {
  .es-proc__item .es-proc__link { display: flex; }

  .es-proc__item:nth-child(2n) .es-proc__link,
  .es-proc__item:last-child .es-proc__link { display: none; }
}

/* Three up. */
@media (min-width: 992px) {
  .es-proc__grid--3 { grid-template-columns: repeat(3, 1fr); }

  .es-proc__grid--3 .es-proc__item .es-proc__link { display: flex; }

  .es-proc__grid--3 .es-proc__item:nth-child(3n) .es-proc__link,
  .es-proc__grid--3 .es-proc__item:last-child .es-proc__link { display: none; }
}

/* Four up. */
@media (min-width: 1200px) {
  .es-proc__grid--4 { grid-template-columns: repeat(4, 1fr); }

  .es-proc__grid--4 .es-proc__item .es-proc__link { display: flex; }

  .es-proc__grid--4 .es-proc__item:nth-child(4n) .es-proc__link,
  .es-proc__grid--4 .es-proc__item:last-child .es-proc__link { display: none; }
}

.es-proc__cta {
  display: flex;
  justify-content: center;
  margin-top: var(--gap-fluid-lg);
}

/* ── Disclosure ────────────────────────────────────────────
   Optional. Only present on a step that passed `details`.

   The rule that matters: the panel is NOT display:none when it is
   shut. It is a grid collapsed to a zero-height row, so the points
   stay in the document, stay indexable and stay findable by the
   browser's own find-in-page. A card whose detail only exists after
   a click has moved the copy out of the page, which is not what was
   asked for; this hides it from the eye and from nothing else.

   `visibility: hidden` at the closed end is what keeps a collapsed
   panel out of the tab order, since a zero-height row still holds
   focusable children otherwise. It is animated on a delay so it does
   not blank the text on the way down. */
.es-proc__more {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  text-align: left;
}

/* min-height is the touch target, not decoration. The row's own content
   is 22px tall, which is a fine thing to look at and too small to hit:
   WCAG 2.5.5 wants 44px and this section is on a page held to A11y 100.
   The padding is what grows it, so the tappable area and the visible
   row are the same rectangle rather than an invisible pad around a
   smaller one. */
.es-proc__more-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  min-height: 44px;
  padding: var(--space-2) 0;
  border: 0;
  background: none;
  color: var(--brand-600);
  font-family: inherit;
  font-size: var(--fs-body-sm);
  font-weight: var(--font-semibold);
  line-height: var(--lh-subhead);
  text-align: left;
  cursor: pointer;
  transition: color var(--duration-normal) var(--ease-out);
}

.es-proc__more-btn:hover { color: var(--brand-700); }

/* The focus ring has to clear the card's own border, hence the offset. */
.es-proc__more-btn:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

/* The mark is a plus that becomes a minus. Two bars, one rotated, so
   there is no second glyph to keep in step with the first. */
.es-proc__more-mark {
  position: relative;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border: 1px solid currentColor;
  border-radius: var(--radius-full);
}

.es-proc__more-mark::before,
.es-proc__more-mark::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 1.5px;
  background: currentColor;
  transform: translate(-50%, -50%);
  transition: transform var(--duration-normal) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out);
}

.es-proc__more-mark::after { transform: translate(-50%, -50%) rotate(90deg); }

/* Open: the upright bar folds into the flat one, so a plus becomes a
   minus in one move rather than swapping icons. */
.es-proc__more-btn[aria-expanded='true'] .es-proc__more-mark::after {
  transform: translate(-50%, -50%) rotate(0deg);
  opacity: 0;
}

/* 0fr to 1fr is the whole animation. It is used instead of max-height
   because it resolves to the panel's real height, so a two-point step
   and a five-point step both open at the same speed and neither ends
   on a pause waiting out a max-height that overshot. */
.es-proc__more-panel {
  display: grid;
  grid-template-rows: 1fr;
}

.es-proc__more-panel > * { overflow: hidden; }

.es-proc__more-btn[aria-expanded='false'] + .es-proc__more-panel {
  grid-template-rows: 0fr;
  opacity: 0;
  visibility: hidden;
}

/* ── Why the transition is behind a class ──────────────────
   The panels are authored open and shut by script on load. If the
   transition were live at that moment the reader would watch four
   panels animate closed on every page view, which is the flash the
   open-by-default markup exists to avoid.

   So: no transition until the script has done its pass and added
   `es-proc--anim`. It cannot be done with an inline `transition:
   none` cleared on the next frame, because requestAnimationFrame
   does not run in a background tab, and a page opened in one would
   keep that inline style for the life of the document and never
   animate again. Ask how this was found. */
.es-proc--anim .es-proc__more-panel {
  transition: grid-template-rows var(--duration-slow) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out),
              visibility 0s;
}

/* Shutting holds visibility until the row has finished collapsing,
   so the text does not blank out above a gap that is still closing. */
.es-proc--anim .es-proc__more-btn[aria-expanded='false'] + .es-proc__more-panel {
  transition: grid-template-rows var(--duration-slow) var(--ease-out),
              opacity var(--duration-normal) var(--ease-out),
              visibility 0s var(--duration-slow);
}

.es-proc__more-list {
  margin: 0;
  padding: var(--space-4) 0 0;
  list-style: none;
}

.es-proc__more-list li {
  position: relative;
  padding-left: var(--space-5);
  color: var(--text-body);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body);
}

.es-proc__more-list li + li { margin-top: var(--space-3); }

/* Dot rather than a tick: these are things the phase covers, not
   things already done, and a tick would claim the second meaning. */
.es-proc__more-list li::before {
  content: '';
  position: absolute;
  top: 0.6em;
  left: var(--space-2);
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--brand-500);
}

/* ── Stepper variant ───────────────────────────────────────
   Everything below is scoped to .es-proc--stepper, so the seven
   other templates composing this partial are untouched by it.
   See the note on `variant` at the top of this file. */

/* The number is a chip in the card's flow now, not a ring standing
   above it, so the card no longer needs to leave room overhead.

   The pointer is on the whole card because the whole card opens it.
   Only where there is a disclosure to open: a card with no `details`
   prints no toggle, and a pointer over something that does nothing is
   a worse lie than a plain cursor. */
.es-proc--stepper .es-proc__card {
  margin-top: 0;
  text-align: left;
}

.es-proc--stepper .es-proc__item:has(.es-proc__more-btn) .es-proc__card {
  cursor: pointer;
}

/* The body copy is still selectable, so the text cursor has to survive
   over it or the card looks like a button all the way through. */
.es-proc--stepper .es-proc__card h3,
.es-proc--stepper .es-proc__sub,
.es-proc--stepper .es-proc__text,
.es-proc--stepper .es-proc__more-list { cursor: text; }

/* Hovering anywhere on a clickable card lights its control, so the
   thing that will happen is shown before the click happens. */
.es-proc--stepper .es-proc__item:hover .es-proc__more-btn { color: var(--brand-700); }

/* align-self is load-bearing. The card is a flex column, so its children
   stretch across it by default, and without this the chip runs the full
   width of the card as a 200px block of tint with a numeral floating in
   the middle of it. */
.es-proc--stepper .es-proc__badge {
  align-self: flex-start;
  width: auto;
  height: auto;
  min-width: 34px;
  min-height: 34px;
  margin: 0 0 var(--space-4);
  padding: 0 var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--brand-50);
  color: var(--brand-700);
  font-size: var(--fs-body-sm);
  /* The ring existed to punch a hole in the connector line behind the
     badge. There is no line and no ground to cut here, so it goes:
     a shadow on a chip sitting flat inside a card reads as a bug. */
  box-shadow: none;
}

/* The chip does not invert on hover the way the ring did. At this size
   a solid brand fill under white text is a small dense block of colour
   four times over in a row, which pulls the eye off the headings. */
.es-proc--stepper .es-proc__item:hover .es-proc__badge {
  border-color: transparent;
  background: var(--brand-100);
  color: var(--brand-700);
}

/* Both the strapline and the duration lose their centring with the
   card. The duration keeps its hairlines: it is still a fact fenced
   off from the paragraphs either side of it. */
.es-proc--stepper .es-proc__time { justify-content: flex-start; }

/* ── Open card ─────────────────────────────────────────────
   An open card carries the same brand border and glow the hover
   state uses, so the card being read is marked while it is open
   rather than only while the pointer is on it. Paint only, in
   keeping with the note on the card block above.

   :has() is doing the work. Where it is unsupported the card simply
   keeps its resting border, which is a lesser card, not a broken
   one.

   The shadow repeats the hover rule's value instead of being grouped
   into that selector list with it, and that is deliberate. A selector
   list containing one selector the engine cannot parse is dropped
   whole, so grouping these would take the hover state down with the
   open state on any browser without :has(). Two rules, one literal
   written twice, is the cheaper mistake. Keep them in step by hand:
   the border differs on purpose, brand-300 against the hover's
   brand-200, because an open card should read as held rather than as
   hovered. */
.es-proc--stepper .es-proc__item:has(.es-proc__more-btn[aria-expanded='true']) .es-proc__card {
  border-color: var(--brand-300);
  box-shadow: 0 18px 40px -20px rgba(232, 93, 32, 0.30), var(--shadow-md);
}

/* ── Panel ─────────────────────────────────────────────────
   The points sit on their own tinted ground inside the card, so an
   open card reads as a card with a panel in it rather than as a
   card that suddenly grew a second half. */
.es-proc--stepper .es-proc__more-list {
  margin-top: var(--space-4);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-2);
  border-radius: var(--radius-md);
  background: var(--brand-50);
}

/* The list already carries the tint's own padding, so the wrapper's
   top gap would double it. */
.es-proc--stepper .es-proc__more-panel .es-proc__more-list { padding-top: var(--space-4); }

.es-proc--stepper .es-proc__more-list li { padding-left: var(--space-5); }

.es-proc--stepper .es-proc__more-list li::before { left: var(--space-1); }

/* ── Natural height ────────────────────────────────────────
   The row does not stretch its cards to match the tallest one.
   Without this, opening one card drags every sibling in its row
   to the same height and leaves a hole in each of them between
   the body copy and the toggle.

   ── This replaced a column layout, and that is the point ────
   The cards were laid out with `column-count: 2` for a while,
   which packs beautifully and fills COLUMN-MAJOR: with four
   cards the first visual row reads 01 03 and the second reads
   02 04. The owner asked for 01 02 then 03 04, and no CSS
   column layout can give that, because filling top-to-bottom
   is what a multi-column container is. Row-major order means a
   grid, so it is a grid.

   This alone still leaves the gap the packed layout below
   exists to close: a grid row cannot start until the tallest
   card in the row above has ended, so an open card in row one
   leaves a void under its shorter neighbour. It is the
   no-JS floor, not the finished layout. */
.es-proc--stepper .es-proc__grid { align-items: start; }

/* ── Packed columns ────────────────────────────────────────
   True masonry packing that still reads 01 02 across the top.

   ── Why this needs three pieces working together ───────────
   Plain CSS gives you one or the other, never both. Multi-column
   packs tightly but fills column-major, so the top row reads
   01 03. A grid reads row-major but cannot start a row before
   the previous one ends. `grid-template-rows: masonry` would
   settle it and ships in no engine.

   So the row structure is made fine-grained instead. Rows are
   8px tall and each card spans however many of them it needs,
   measured by the script at the foot of this file. Then:

     1. the column is ASSIGNED, odd cards left, even cards
        right, so the reading order can never drift the way it
        did under column-count. This is the piece that makes
        the layout honest.
     2. `dense` lets a card back-fill the earliest free run of
        rows in its own column, which is what actually closes
        the gap: card 04 rises to sit under card 02 instead of
        waiting for card 03's row.
     3. row-gap is 0 and the rhythm comes from the item's own
        margin, because a gap between 8px rows would be applied
        between every row inside a card's span as well, making
        the grain 33px rather than 8px and putting most of the
        gap back.

   Enhancement only. `--es-proc-packed` is added by the script
   after it has measured, so a page with no JS keeps the plain
   grid above and every card is still readable, just less
   tightly packed. */
.es-proc--stepper {
  /* The row grain, and it is 1px for a reason. A card's span rounds UP to
     whole rows, so the grain is also the worst-case slack added under
     every card. At 8px the vertical gaps measured 39 and 42px against a
     24.8px column gap, which reads as the columns being spaced differently
     from the rows. At 1px the gap is the card's own margin plus at most a
     pixel, so vertical and horizontal spacing match.

     The cost is implicit rows: roughly 600 per card instead of 75. Grid
     handles a few thousand implicit rows without noticing, and there are
     four cards. */
  --es-proc-row: 1px;

  /* The stagger. Only the head of the second column carries it;
     the card below it inherits the offset by sitting under it,
     so one declaration drops the whole column rather than
     opening a second gap between 02 and 04. */
  --es-proc-stagger: 48px;
}

@media (min-width: 768px) {
  .es-proc--stepper.es-proc--packed .es-proc__grid--2 {
    grid-auto-flow: row dense;
    grid-auto-rows: var(--es-proc-row);
    row-gap: 0;
  }

  .es-proc--stepper.es-proc--packed .es-proc__grid--2 > .es-proc__item {
    grid-row-end: span var(--es-proc-span, 1);
    margin-bottom: var(--es-proc-gap);
  }

  .es-proc--stepper.es-proc--packed .es-proc__grid--2 > .es-proc__item:nth-child(odd) {
    grid-column: 1;
  }

  .es-proc--stepper.es-proc--packed .es-proc__grid--2 > .es-proc__item:nth-child(even) {
    grid-column: 2;
  }

  .es-proc--stepper.es-proc--packed .es-proc__grid--2 > .es-proc__item:nth-child(2) {
    margin-top: var(--es-proc-stagger);
  }
}

/* ── The always-open card ──────────────────────────────────
   Its toggle cannot collapse it, and the cursor should say so
   before the click does. The colour is left alone: this is the
   active card, and greying its control out would make the one
   card being read look like the disabled one. */
.es-proc__more-btn[aria-disabled='true'] { cursor: default; }

/* Nothing here moves, so this only stills the colour fades. */
@media (prefers-reduced-motion: reduce) {
  .es-proc__card,
  .es-proc__badge { transition: none; }

  /* The panel still opens and shuts, it just arrives rather than
     travels. The row jump is the point of the control, so it is not
     something to remove, only something to stop animating. */
  .es-proc--anim .es-proc__more-panel,
  .es-proc--anim .es-proc__more-btn[aria-expanded='false'] + .es-proc__more-panel,
  .es-proc__more-mark::before,
  .es-proc__more-mark::after { transition: none; }
}
