/* The homepage: thirteen sections, drawn in design/claude-design/latest/HOME ORIGINAL.dc.html.
 *
 * MOBILE FIRST. Every rule below is the phone layout, and every media query
 * adds columns as the screen widens, at the design's own breakpoints (560,
 * 600, 640, 820, 900, 1000, 1100, 1200). The design is drawn desktop-first,
 * and two of its layouts break on phones as drawn — the hero clips its
 * headline, and the rail's pills do not fit — so each is fixed here, and each
 * departure is in docs/BASELINE.md §5.
 *
 * LOADED ON THE HOMEPAGE ONLY, AND IT NEVER STYLES THE SHELL. No bare element
 * selectors, no header, drawer, menu or footer classes: core/tests_design.py
 * holds it to that, because the scaffold stylesheet this replaces reached the
 * header three ways.
 *
 * NO COLOUR THAT IS NOT A TOKEN, except white and the alpha steps of white
 * and of the design's ink (rgba(23,23,26,…) corner fades). Every ground,
 * mesh, glow and shadow is in tokens.css with the line of the design it came
 * from.
 *
 * TWO KINDS OF COMPONENT, the same split tokens.css makes. The light
 * sections read the themed tokens. The dark slabs and the dark commitment
 * cards carry fixed dark tokens; the white cards are light islands
 * (`ed-light`) wherever they sit. Nothing in between.
 *
 * LOGICAL PROPERTIES THROUGHOUT, so the page mirrors under Arabic from the
 * `dir` attribute alone; the few gradients and nudges that have a direction
 * carry an explicit [dir="rtl"] twin.
 */

/* ---- Shared ------------------------------------------------------------ */

/* Anchors clear the sticky bar by 24px, as the design does (HOME:86): the
 * root's scroll-padding (layout.css, "Focus") plus these 8px, on every
 * section and on each What we do card, which the design's own rule reaches
 * too ("section[id], article[id]"). The form inside #contact has its own, in
 * layout.css. */
.ed-hs[id],
.ed-practice[id] { scroll-margin-top: 8px; }


/* Card lists are lists for a screen reader and nothing else. */
.ed-pillar__list,
.ed-stats,
.ed-outcomes__row,
.ed-press__tiles,
.ed-offer__steps,
.ed-doc__findings,
.ed-index,
.ed-stack__layers,
.ed-engage__grid,
.ed-contact__steps,
.ed-hero__proof {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The figures and the numbered labels use tabular numerals, as the design's
 * global rule has them (HOME: "[data-tnum], [style*="IBM Plex Mono"]").
 * Only Archivo's figures look any different for it: IBM Plex Mono and IBM
 * Plex Sans draw every figure one width already (measured: the same widths
 * with it and without), so it is not repeated on every other mono label,
 * where it would change nothing. */
.ed-stat__figure,
.ed-score__figure,
.ed-pillar__num,
.ed-practice__num,
.ed-index__num,
.ed-offer__num,
.ed-contact__num,
.ed-doc__fnum,
.ed-doc__pnum,
.ed-doc__dur { font-variant-numeric: tabular-nums; }

.ed-icon,
.ed-stat__svg,
.ed-practice__svg,
.ed-practice__arrow,
.ed-rail__chev { display: block; }

/* TABS: ONE ROW, shared by the Industries sectors and the three ways we work
 * (the owner, 3 and 4 October). Each tab is its number and its name; what a
 * tab looks like is its section's: the three ways are a segmented pill (What
 * we do), the sectors tiles (Industries).
 *
 * ON A PHONE THE ROW SCROLLS SIDEWAYS, every name on one line, so a long name
 * ("Integration-heavy", "Staff augmentation") is never squeezed into a
 * quarter of 280px or clipped; the next tab showing at the edge says there
 * is more. The row's padding holds the focus ring (3px out, 2px wide) inside
 * the scroller, and its negative margin puts the first tab back on the
 * column's edge. Without the script the tabs are in-page links to panels
 * that all show (sections/industries.html, sections/services.html). The
 * keyboard ring is in the text link's purple. */
.ed-tabrow {
  --ed-focus: var(--ed-link);
  display: flex;
  gap: 8px;
  margin: -6px;
  padding: 6px;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-padding-inline: 6px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}
.ed-tabrow > li { display: flex; flex: 0 0 auto; min-width: 0; scroll-snap-align: start; }
.ed-tab {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-block-size: var(--ed-target);
  padding: 10px 14px;
  font-family: var(--ed-font-display);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--ed-transition), border-color var(--ed-transition),
              background-color var(--ed-transition), box-shadow var(--ed-transition);
}
.ed-tab__num {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.15em;
  color: var(--ed-purple);
}
.ed-tab__name {
  font-size: var(--ed-size-small);
  font-weight: var(--ed-weight-bold);
  line-height: 1.25;
  letter-spacing: -0.01em;
}
/* In forced colours, where fills and shadows are dropped, the chosen tab of
 * either kind takes the system's Highlight: one class deeper than either
 * section's own chosen tab, so it wins wherever those come in the file. */
@media (forced-colors: active) {
  .ed-tabrow .ed-tab[aria-selected="true"] {
    forced-color-adjust: none;
    background: Highlight;
    border-color: Highlight;
    color: HighlightText;
  }
  .ed-tabrow .ed-tab[aria-selected="true"] :is(.ed-tab__num, .ed-tab__name, .ed-sectors__sub) { color: HighlightText; }
}

/* ---- Hero (HOME:588-616) ---------------------------------------------- */

.ed-hero {
  position: relative;
  background: var(--ed-dark-panel);
  color: var(--ed-on-dark);
  --ed-focus: var(--ed-cta);
}

/* A MINIMUM, NOT A HEIGHT (BASELINE.md §5). The design's hero is
 * clamp(594px,84vh,924px) with the bar over its top; since 2 October it is
 * 77% of the window, 557-852px (the owner: "reduce height of hero", then
 * "in mid of what it was and what now" against 70%: 770px on a 1728 x 1000
 * window, where it was 840px). Since 28 September the bar
 * is transparent there (layout.css), so the hero slides up under the sticky
 * bar by its height, its copy kept clear of the bar: the copy is 533px at
 * most on a desktop, so the box never has to grow there; on a phone it
 * grows to the copy. svh so the box does not jump as a phone's toolbar
 * shows and hides; the vh line is for browsers without it. */
.ed-hero { margin-block-start: calc(-1 * var(--ed-header-h)); }
.ed-hero__box {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  padding-block-start: var(--ed-header-h);
  min-height: clamp(557px, 77vh, 852px);
  min-height: clamp(557px, 77svh, 852px);
  /* Clip, not hidden, where the browser knows it: a hidden box can still be
   * scrolled by script, and bringing a focused tab "into view" scrolled the
   * photographs up inside it, uncovering a band of bare photo at the foot
   * (measured, 4 October). A clipped box cannot scroll at all. */
  overflow: hidden;
  overflow: clip;
  background: var(--ed-dark-panel);
}

/* ONE PHOTOGRAPH PER SLIDE, stacked: the chosen slide's shows, the others
 * wait at nothing (js/home.js crossfades them). The layer clips its own
 * photographs, so the slow zoom never widens the hero. */
.ed-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  overflow: clip;
}
.ed-hero__shot {
  position: absolute;
  inset: 0;
  opacity: 0;
}
.ed-hero__shot[data-on] { opacity: 1; }
.ed-hero__shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The grid (HOME:594): white at 7%, then halved. */
.ed-hero__box::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  background-image:
    linear-gradient(to right, var(--ed-hero-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--ed-hero-grid) 1px, transparent 1px);
  background-size: clamp(72px, 7vw, 124px) clamp(72px, 7vw, 124px);
}

/* The scrim (HOME:595): the same 9deg layer under Arabic, as drawn. */
.ed-hero__box::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: var(--ed-hero-scrim);
}
.ed-hero--photo .ed-hero__box::after { background: var(--ed-hero-scrim-photo); }

/* The copy is pinned to the bottom, as drawn. The top padding is the gap
 * under the bar for when the copy outgrows the minimum, on a short phone.
 *
 * A GRID, SO THE PAUSE BUTTON CAN COME FIRST IN THE MARKUP (the reading and
 * tab order: the WAI-ARIA carousel pattern) and still be drawn at the bottom
 * right, beside the tabs: slides, then the proof line, then the tabs and
 * the button, as before. The tabs' column may shrink (minmax(0, ...)), so
 * their row scrolls sideways on a phone; mirrored under Arabic with the
 * writing direction. */
.ed-hero__inner {
  --hero-bar-gap: clamp(18px, 2vw, 28px);
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "slides slides"
    "proof proof"
    "tabs toggle";
  column-gap: 16px;
  padding-block: clamp(24px, 4vw, 48px) clamp(40px, 5.4vw, 80px);
}

/* THE SLIDES SHARE ONE GRID CELL, so the hero is as tall as the tallest and
 * nothing below it moves when a slide changes. Each sits on the cell's
 * floor, over the proof line, as the one slide did. One that is not chosen
 * is hidden from sight, from the tab order and from screen readers alike. */
.ed-hero__slides { grid-area: slides; display: grid; }
.ed-hero__copy {
  grid-area: 1 / 1;
  align-self: end;
  max-width: 1040px;
}
.ed-hero__copy:not([data-on]) { visibility: hidden; }

/* ...ALL BUT THE PAGE'S <h1>, which stays in the accessibility tree while
 * another slide shows: otherwise, for two slides in three, the page had no
 * level-one heading and the hero's region was named by a heading that was
 * not there. It keeps its room in its own slide, so nothing moves; it is
 * drawn at nothing (fading out with its slide), lets the pointer and a text
 * selection through to the slide that shows, and comes back with its
 * slide. */
.ed-hero__copy:not([data-on]) > h1.ed-hero__title {
  visibility: visible;
  opacity: 0;
  pointer-events: none;
  user-select: none;
  transition: opacity var(--ed-duration-crossfade) ease;
}

.ed-hero__eyebrow {
  max-width: min(640px, var(--hero-copy-cap, 100%));
  margin: 0 0 clamp(14px, 1.4vw, 18px);
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-caption);
  font-weight: var(--ed-weight-regular);
  line-height: 1.7;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ed-hero-eyebrow);
}

/* At most 13em, the design's own measure with room: its second line, "when
 * the business scales", is 10.6em. A longer headline ("AI, from proof of
 * concept to production") balances over two lines rather than running under
 * the photograph's subject, which sits right of the copy (docs/BASELINE.md
 * §5). */
.ed-hero__title {
  max-width: 13em;
  margin: 0 0 clamp(20px, 2.2vw, 28px);
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-h1);
  font-weight: var(--ed-weight-bold);
  line-height: 1.08;
  letter-spacing: -0.028em;
  color: var(--ed-on-dark);
  text-wrap: balance;
}

.ed-hero__lede {
  max-width: min(580px, var(--hero-copy-cap, 100%));
  margin: 0 0 clamp(26px, 2.8vw, 36px);
  font-size: var(--ed-size-lead-lg);
  line-height: 1.58;
  color: var(--ed-on-dark-90);
  text-wrap: pretty;
}

.ed-hero__actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* ON A TABLET THE WORDS KEEP TO THE START HALF, as on a desktop, where the
 * lede's 580px is about half the row: the photograph's subject sits in the
 * end half (the owner, 4 October: "the face sits right of the text and
 * scrim"). The hero fills its height with the photo there, so a portrait's
 * face is 300-450px wide and already at the far edge; with the lede across
 * 84% of the row (580px at 768) it ran over the face's lower half, mouth
 * and chin (review, 4 October; measured at 600-1023px, portrait and
 * landscape). At 55% the eyebrow and the lede clear it by 37px or more at
 * every tablet size measured, 600 to 1023px wide and 700 to 1366px tall;
 * the headline (13em) already did, by 15px or more. The range is the tablet
 * photograph's (its <source> in sections/hero.html, 600-1023px), in em like
 * every breakpoint here: at the default text size the two are the same, and
 * with larger text the phone layout keeps the words longer. Phones lay the
 * words over the whole photo, as drawn. */
@media (min-width: 37.5em) and (max-width: 63.9375em) {
  .ed-hero--photo { --hero-copy-cap: 55%; }
}

/* A long label wraps inside its pill (.ed-btn--wrap) rather than pushing
 * the page sideways, and here its lines start at the padding, as the
 * design's do (French wraps at 390px). The secondary label is 278px wide in
 * a 280px column at 320px. */
.ed-hero__btn { text-align: start; }

.ed-hero__proof {
  grid-area: proof;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px clamp(16px, 1.8vw, 26px);
  margin-block-start: clamp(22px, 2.4vw, 32px);
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-eyebrow);
  font-weight: var(--ed-weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ed-on-dark);
}
/* The dots between items, drawn rather than typed, each its own item as
 * drawn (HOME:696-702): when the row wraps, a dot ends the line and the next
 * item starts at the gutter. */
.ed-hero__dot {
  flex: 0 0 auto;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--ed-hero-dot);
}

/* THE TABS AND THE PAUSE BUTTON, along the hero's floor (the owner, 4
 * October, after Okta's pattern; no hairline over them since his polish
 * that evening), in the last row of the hero's grid.
 *
 * HIDDEN IN PLACE until js/home.js answers them: `hidden` makes them
 * invisible, and so out of the tab order and the accessibility tree, but
 * keeps their room, so revealing them moves nothing. When they took no room
 * until the script ran, the reveal lifted the copy 75px on every load, after
 * the first paint: a layout shift of about 0.048, half the budget for a
 * "good" page (measured, 4 October review). Under reduced motion there is
 * no turning, so no pause button, from the first paint.
 *
 * THE TABS: uppercase mono, the chosen one white and semibold (no line
 * under it since the same polish), the others the neutral on-dark label
 * (--ed-label-on-dark): about 11:1 on the scrim's floor, and over 9:1 even
 * on a white photograph, since both scrim layers are 90% near-black or more
 * down there. On a phone the row scrolls sideways beside the button, each
 * name on one line; its padding holds the focus ring inside the scroller.
 *
 * THE PAUSE BUTTON: round, 48px, its outline a ring that fills over each
 * slide's --ed-hero-slide (js/home.js runs it: the ring IS the timer).
 * Pause shows two bars; paused, a triangle. */
.ed-hero__bar {
  grid-area: tabs;
  align-self: center;
  display: flex;
  min-width: 0;
  margin-block-start: var(--hero-bar-gap);
}
.ed-hero__bar[hidden],
.ed-hero__toggle[hidden] { visibility: hidden; }
.ed-hero__tabs {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: clamp(20px, 2.8vw, 44px);
  margin: -6px;
  padding: 6px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.ed-hero__tab {
  flex: 0 0 auto;
  min-block-size: var(--ed-target);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ed-label-on-dark);
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-eyebrow);
  font-weight: var(--ed-weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--ed-transition-quick);
}
/* White on the label grey is only 1.66:1, under the 3:1 a lightness change
 * needs to mark a state by itself (SC 1.4.1): so the chosen tab is also
 * semibold, a mark that is not colour, and a hovered tab lightens short of
 * white and keeps its weight, so it never looks chosen. Plex Mono keeps one
 * advance width at every weight, so the row never moves. */
.ed-hero__tab:hover { color: var(--ed-on-dark-90); }
.ed-hero__tab[aria-selected="true"] {
  color: var(--ed-on-dark);
  font-weight: var(--ed-weight-semibold);
}
/* Forced colours paint every tab the one text colour, so there, and only
 * there, the chosen tab is underlined too. */
@media (forced-colors: active) {
  .ed-hero__tab[aria-selected="true"] {
    text-decoration: underline 2px;
    text-underline-offset: 6px;
  }
}

.ed-hero__toggle {
  grid-area: toggle;
  align-self: center;
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  margin-block-start: var(--hero-bar-gap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ed-on-dark);
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .ed-hero__toggle { display: none; }
}
.ed-hero__ring {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  rotate: -90deg;
  fill: none;
  stroke-width: 2;
}
.ed-hero__ring-track {
  stroke: var(--ed-on-dark-rule);
  transition: stroke var(--ed-transition-quick);
}
.ed-hero__toggle:hover .ed-hero__ring-track { stroke: var(--ed-on-dark-50); }
.ed-hero__ring-fill {
  stroke: currentColor;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
.ed-hero__icon {
  inline-size: 16px;
  block-size: 16px;
  fill: currentColor;
}
.ed-hero__toggle[data-paused] .ed-hero__icon--pause,
.ed-hero__toggle:not([data-paused]) .ed-hero__icon--play { display: none; }

/* ---- Who we are (HOME:618-698) ---------------------------------------- */

.ed-about { background: var(--ed-ground-about); }

.ed-about__ledes p {
  margin: 0 0 18px;
  font-size: var(--ed-size-lead);
  line-height: 1.65;
  color: var(--ed-ink);
  text-wrap: pretty;
}
.ed-about__ledes p:last-child { margin-block-end: 0; }

/* THE THREE WAYS WE WORK AS HORIZONTAL TABS (the owner, 4 October): the
 * shared tab row ("Tabs", under Shared at the top), its three tabs side
 * by side from 600px and scrolling sideways below that, then one way at a
 * time. Without the script all three panels show, one under the other. With
 * it, the panels share one grid cell, so a crossfade has both in place, and
 * the cell is always the TALLEST way's height (the owner, 7 October: "the
 * panel height never changes when the tab changes"): a hidden way keeps its
 * place in the cell, invisible (.ed-pillar[hidden], below), so no script
 * measures anything and nothing below moves on any tab. */
.ed-ways { margin-block-start: clamp(30px, 3.2vw, 48px); }
.ed-ways[id] { scroll-margin-top: 8px; }
.ed-ways__panels {
  display: grid;
  gap: clamp(20px, 2.4vw, 40px);
  margin-block-start: clamp(22px, 2.4vw, 34px);
}
.ed-ways[data-tabs-ready] > .ed-ways__panels > .ed-pillar { grid-area: 1 / 1; }

/* THE TABS ARE A SEGMENTED PILL (the owner, 4 October): the three sit in one
 * light-grey rounded track; the chosen one is a white pill raised on a soft
 * shadow, its number in purple and its name near-black; the others are
 * plain text on the track. No dark tile and no magenta line. The others'
 * words are --ed-muted, 4.85:1 on the track and 3.2:1 apart from the chosen
 * one's ink, so the choice shows in lightness as well as in the pill, and
 * in forced colours it takes the system's Highlight ("Tabs").
 *
 * The track is the row that scrolls sideways on a phone if it must: it sits
 * on the column's edge, and its 5px of padding holds a pill's focus ring
 * (3px out, 2px wide), concentric with the track's own rounded end. There
 * the pills sit 2px apart with 12px either side, so the words of the next
 * one are cut at the track's end and say there is more (measured:
 * "Consultancy" cut at 320px, "03" showing from 360px). From 600px the
 * three share it evenly ("Wider screens"). */
.ed-ways__tabs {
  gap: 2px;
  margin: 0;
  padding: 5px;
  background: var(--ed-segment-track);
  border-radius: var(--ed-radius-pill);
  scroll-padding-inline: 5px;
}
.ed-ways__tab {
  flex-direction: row;
  gap: 6px;
  padding: 10px 12px;
  border-radius: var(--ed-radius-pill);
  color: var(--ed-muted);
}
.ed-ways__tab .ed-tab__num { color: var(--ed-muted); }
.ed-ways__tab:not([aria-selected="true"]):hover { color: var(--ed-link); }
.ed-ways__tab[aria-selected="true"] {
  background: var(--ed-surface);
  box-shadow: var(--ed-segment-shadow);
  color: var(--ed-ink);
}
.ed-ways__tab[aria-selected="true"] .ed-tab__num { color: var(--ed-purple); }

/* THE THREE WAYS WE WORK, under the What we do cards (the owner, 2 October,
 * from a screenshot of the design's next pass, without its Commercial model
 * rows): the number and an optional tag in purple mono on one line, then who
 * owns what and what each includes. No rule across the top since 4 October
 * (the owner: "remove the full-width purple line"). Brand colours only, as
 * on every page that is not a service's. */
.ed-pillar {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: clamp(24px, 4vw, 72px);
  align-content: start;
  min-width: 0;
}
/* A HIDDEN WAY STAYS IN ITS PLACE, OUT OF SIGHT (the owner, 7 October). The
 * display above beats the hidden attribute's display: none on purpose: every
 * way keeps its box in the cell the three share, so the cell is the tallest
 * one's height whichever is chosen, and visibility takes the hidden ones out
 * of sight, out of the tab order and away from a screen reader. Only the
 * script hides a way, as it makes the tabs (js/home.js). */
.ed-pillar[hidden] { visibility: hidden; }
.ed-pillar:focus-visible { outline-offset: 4px; }
.ed-pillar__intro,
.ed-pillar__includes,
.ed-pillar__side,
.ed-pillar__detail { min-width: 0; }

/* ON A PHONE, ONE COLUMN: the way, its photograph, what it includes, then
 * who owns what. The right column's wrapper steps aside (display: contents;
 * a plain div, so nothing is lost to a screen reader) and the photograph
 * moves up under the description. It is decoration, so the order the panel
 * is read and tabbed in is the markup's, unchanged. The 12px over who owns
 * what is the gap that stood between the two columns. */
.ed-pillar__side { display: contents; }
.ed-pillar__intro,
.ed-pillar__photo { order: -1; }
.ed-pillar__detail { margin-block-start: 12px; }

/* THE WAY'S PHOTOGRAPH (the owner, 7 October): short and wide, 16:7, with
 * the card's radius, on the light grey until it arrives. Never wider than
 * its 1x rendition (560px, home/ways.py): between 600 and 900px, where the
 * panel is still one column, it stops there rather than be drawn larger than
 * it was made. Its width and height are in the markup, so nothing moves as it
 * arrives. */
.ed-pillar__photo {
  display: block;
  inline-size: 100%;
  max-inline-size: 560px;
  block-size: auto;
  aspect-ratio: 16 / 7;
  margin-block-start: 22px;
  object-fit: cover;
  border-radius: var(--ed-radius-card);
  background: var(--ed-bg-alt);
}

.ed-pillar__marker {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-block-end: clamp(16px, 1.6vw, 22px);
}
.ed-pillar__num,
.ed-pillar__tag {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  color: var(--ed-purple);
}
.ed-pillar__num { letter-spacing: 0.15em; }
.ed-pillar__tag {
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  text-align: end;
}

.ed-pillar__title {
  margin: 0 0 11px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-card-title);
  font-weight: var(--ed-weight-bold);
  line-height: 1.14;
  letter-spacing: var(--ed-track-snug);
  color: var(--ed-ink);
}

.ed-pillar__body {
  margin: 0;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-body);
  text-wrap: pretty;
}

/* "Includes" and the stat cards' sources are labels inside a card, in its
 * royal blue role (--ed-card-label): 7.32:1 on white, about 6.4:1 at worst
 * under the section's corner fade. */
.ed-pillar__label {
  margin: 22px 0 12px;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-card-label);
}

.ed-pillar__list {
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-size: var(--ed-size-body);
  line-height: 1.45;
  color: var(--ed-body);
}
/* The way's own button closes its left column, under what it includes (the
 * owner, 4 October). */
.ed-pillar__cta { margin-block-start: 26px; }

/* Each item is ticked, the tick drawn in CSS in brand purple (no icon to
 * fetch, nothing inline): two borders of a box turned 45 degrees, centred on
 * the item's first line. */
.ed-pillar__list > li {
  position: relative;
  padding-inline-start: 26px;
}
.ed-pillar__list > li::before {
  content: "";
  position: absolute;
  inset-inline-start: 3px;
  inset-block-start: calc(0.5lh - 7px);
  inline-size: 5px;
  block-size: 10px;
  border: solid var(--ed-purple);
  border-width: 0 2px 2px 0;
  rotate: 45deg;
}

/* WHO OWNS WHAT ON ONE SCALE (the owner, 4 October: the marks glide to their
 * new owner as the tabs change). The three owners are columns, from us to
 * you: EvolveDash, shared, your team, named once above the rows. Each part
 * of the work is a hairline row with its mark in its owner's column, on a
 * line through all three: filled for EvolveDash, half-filled for shared, a
 * ring for your team, so the shape says it as well as the place. The words
 * are in each row for a screen reader; the scale and the marks are
 * decoration. On a phone the part of the work sits over its scale, which
 * then takes the full width; from 480px they share a line. */
.ed-owners__scale,
.ed-owners__row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: center;
}
.ed-owners__scale {
  padding-block-end: 4px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-caption);
  font-weight: var(--ed-weight-semibold);
  line-height: 1.3;
  text-align: center;
  color: var(--ed-body);
}
.ed-owners__scale > :first-child { display: none; }
.ed-owners { margin: 0 0 4px; }
.ed-owners__row {
  row-gap: 4px;
  padding-block: 10px;
  border-block-end: 1px solid var(--ed-border);
}
.ed-owners__row > dt {
  grid-column: 1 / -1;
  min-width: 0;
  font-size: var(--ed-size-body);
  line-height: 1.45;
  color: var(--ed-body);
}
.ed-owner {
  grid-column: 1 / -1;
  min-width: 0;
  margin: 0;
}
.ed-owner--evolvedash { --owner-at: calc(100% / 6); }
.ed-owner--shared { --owner-at: 50%; }
.ed-owner--client { --owner-at: calc(500% / 6); }
.ed-owner__track {
  position: relative;
  display: block;
  block-size: 20px;
}
/* The line through the three columns, and a small stop in each. */
.ed-owner__track::before {
  content: "";
  position: absolute;
  inset-inline: calc(100% / 6);
  inset-block-start: calc(50% - 0.5px);
  block-size: 1px;
  background: var(--ed-border);
}
.ed-owner__track::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, var(--ed-rule) 0 2.5px, transparent 3px) 0 50% / calc(100% / 3) 100% repeat-x;
}
.ed-owner__mark {
  position: absolute;
  z-index: 1;
  inset-block-start: 50%;
  inset-inline-start: var(--owner-at);
  inline-size: 12px;
  block-size: 12px;
  /* Centred on its column by margins, not a translate: the glide is a
   * GSAP transform, and the two must not fight over one property. */
  margin-block-start: -6px;
  margin-inline-start: -6px;
  border: 2px solid var(--ed-purple);
  border-radius: 50%;
  background: var(--ed-surface);
}
.ed-owner--evolvedash .ed-owner__mark { background: var(--ed-purple); }
.ed-owner--shared .ed-owner__mark { background: linear-gradient(90deg, var(--ed-purple) 50%, var(--ed-surface) 50%); }
.ed-owner--shared .ed-owner__mark:dir(rtl) { background: linear-gradient(270deg, var(--ed-purple) 50%, var(--ed-surface) 50%); }
@media (forced-colors: active) {
  .ed-owner__mark { forced-color-adjust: none; border-color: CanvasText; background: Canvas; }
  .ed-owner--evolvedash .ed-owner__mark { background: CanvasText; }
  .ed-owner--shared .ed-owner__mark { background: linear-gradient(90deg, CanvasText 50%, Canvas 50%); }
}

.ed-stats {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 1.5vw, 18px);
  margin-block-start: clamp(34px, 3.8vw, 58px);
}

/* EACH CARD IS TWO ROWS OF THE ROW IT SITS IN (a subgrid): its byline and
 * its figure, so the figures stay in one line across the row whatever a
 * byline does. "Third-party marketplaces", the "Job success" card's (the
 * owner, 4 October 2026), is a line longer than the narrowest card holds
 * at 1100-1214px and 560-575px (measured), and every byline wraps under
 * 32px browser text; then every head in the row grows together. Where
 * subgrid is unknown the card is a plain two-row grid, as tall as its
 * row, the old layout. */
.ed-stat {
  grid-row: span 2;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0;
  min-width: 0;
  background: var(--ed-surface);
  border-radius: var(--ed-radius-card);
  overflow: hidden;
  box-shadow: var(--ed-stat-shadow);
  transition: transform var(--ed-duration-card) var(--ed-ease), box-shadow var(--ed-duration-card) ease;
}
.ed-stat:hover { transform: translateY(-2px); box-shadow: var(--ed-stat-shadow-hover); }

.ed-stat__head {
  align-self: start;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 18px 0;
}
.ed-stat__icon { display: flex; flex: 0 0 auto; color: var(--ed-purple); }
.ed-stat__by { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ed-stat__name {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-small);
  font-weight: var(--ed-weight-semibold);
  color: var(--ed-ink);
}
.ed-stat__source {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* The design never wraps it. With 32px browser text it ran past the card,
   * so it may (a11y plan item 21; docs/BASELINE.md §5), and since 4 October
   * "Third-party marketplaces" wraps at the default size too where the card
   * is narrowest (the subgrid above keeps the figures in line). */
  overflow-wrap: anywhere;
  color: var(--ed-card-label);
}

.ed-stat__body { padding: 18px 18px clamp(18px, 1.9vw, 22px); }
.ed-stat__figure {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-figure);
  font-weight: var(--ed-weight-bold);
  line-height: 0.95;
  letter-spacing: -0.035em;
  color: var(--ed-ink);
}
.ed-stat__caption {
  margin: 10px 0 0;
  font-size: var(--ed-size-body);
  line-height: 1.55;
  color: var(--ed-stat-caption);
  text-wrap: pretty;
}

/* ---- What we do (HOME:700-804) ----------------------------------------- */

.ed-services { background: var(--ed-ground-services); }
.ed-services__lede { max-width: var(--ed-lede-maxw); margin-block-end: clamp(28px, 3.2vw, 48px); }
/* "Discuss a service" keeps the 4px under its line that the design gives it
 * (HOME:798). */
.ed-services .ed-split > .ed-link { padding-block-end: 4px; }

/* THE RAIL — PROTECTED DESIGN. Every value below is the design's inline
 * value for the same element (HOME:710-802, 88-91, 121-122), moved here
 * because the CSP will not run an inline style.
 *
 * It bleeds to the container's edge, fading in over one gutter at the start
 * and the drawn 74px (--ed-rail-fade) at the end.
 *
 * THE ROW IS A LOOP (the owner, 7 October 2026; js/home.js): after card 06
 * comes 01 and before 01 comes 06, so there is no end, and both fades stay.
 * At rest card 06 peeks in to the left of card 01 under the start fade.
 * (From 27 September until then the end fade went once the row reached its
 * end.) Without the script the row is the six, as drawn, fades and all.
 *
 * TWO MOTIONS ADDED TO THE CARDS: the aurora silk on hover and keyboard focus
 * (the owner, 7 October, below), and the loop. At rest they are the
 * design's, pixel for pixel. */
.ed-rail-mask {
  margin-inline: calc(-1 * var(--ed-gutter));
  -webkit-mask-image: linear-gradient(90deg, transparent 0, black var(--ed-gutter), black calc(100% - var(--ed-rail-fade)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, black var(--ed-gutter), black calc(100% - var(--ed-rail-fade)), transparent 100%);
}
.ed-rail-mask:dir(rtl) {
  -webkit-mask-image: linear-gradient(270deg, transparent 0, black var(--ed-gutter), black calc(100% - var(--ed-rail-fade)), transparent 100%);
  mask-image: linear-gradient(270deg, transparent 0, black var(--ed-gutter), black calc(100% - var(--ed-rail-fade)), transparent 100%);
}

.ed-rail {
  display: flex;
  gap: clamp(14px, 1.4vw, 18px);
  align-items: stretch;
  overflow-x: auto;
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;
  /* 36px above and 52px below, taken back by the margins, so the hover
   * glow is never clipped by the scroller (28 September). */
  padding-block: 36px 52px;
  margin-block: -36px -52px;
  padding-inline: var(--ed-gutter);
  /* Whatever the browser scrolls into view here (keyboard focus,
   * find-in-page) stops clear of both fades, with or without js/home.js.
   * Measured with the script off: the worst focused control went from 6%
   * visible to 40%, and the script clears the rest. */
  scroll-padding-inline: var(--ed-gutter) var(--ed-rail-fade);
  /* CARD BY CARD (the owner, 7 October: "scroll-snap kept"): a swipe, a
   * trackpad, a wheel or an arrow press comes to rest with a card's start
   * where the drawn row starts it, one gutter in, which is also where the
   * loop deals the row again (js/home.js). */
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.ed-rail::-webkit-scrollbar { display: none; }

.ed-practice {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  flex: 0 0 clamp(252px, 25vw, 326px);
  min-width: 0;
  scroll-snap-align: start;
  background:
    radial-gradient(128% 104% at 18% 128%, rgb(var(--pc-glow) / var(--pc-glow-a, 0.34)) 0%, rgb(255 255 255 / 0) 58%),
    radial-gradient(112% 116% at 74% 136%, rgb(var(--pc-glow) / var(--pc-glow-b, 0.2)) 0%, rgb(255 255 255 / 0) 60%),
    #FFFFFF;
  background-size: 100% 100%;
  border: 1px solid var(--ed-border);
  border-radius: var(--ed-radius-card);
  overflow: hidden;
  box-shadow: var(--ed-card-shadow);
  --orbit-glow: 0;
  transition: transform 0.45s var(--ed-ease), --orbit-glow 0.45s ease,
              background-size 0s linear var(--ed-duration-aurora-settle);
  animation: ed-orbit var(--ed-duration-orbit) linear infinite paused;
}
/* THE HOVER GLOW (HANDOFF.md, "Service card hover glow", 28 September,
 * night): one glow for all six cards, seven lights, one per practice in its
 * light-ground glow colour plus brand magenta, in the design's order round
 * the card: Web, Design & UX, AI, Data, Mobile & XR, Growth, brand. Each
 * sits 9px out in its own direction, 51.43deg apart, with a 14px blur and a
 * -10px spread, at the strength the design gives it (tokens.css), and the
 * lights orbit once every 2.5s, alternate lights the other way, so the
 * colours keep crossing. On hover or focus the glow fades in over 0.45s and
 * the orbit runs; off hover it fades out and the orbit pauses where it is,
 * so it never snaps. The card lifts 4px on the same ease; no ring and no
 * border colour. Reduced motion stops the orbit, and layout.css's cut to
 * every transition makes the fade and the lift instant, where HANDOFF.md
 * keeps the fade (docs/BASELINE.md §5). Where a browser cannot compute the
 * lights (no cos() in CSS), the card keeps its resting shadow and the lift. */
@property --orbit-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@property --orbit-glow { syntax: "<number>"; inherits: false; initial-value: 0; }
@keyframes ed-orbit { to { --orbit-angle: 360deg; } }
@supports (box-shadow: calc(cos(0deg) * 1px) 0 0 red) {
  .ed-practice {
    box-shadow:
      calc(cos(var(--orbit-angle)) * var(--ed-orbit-radius)) calc(sin(var(--orbit-angle)) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-web-glow) / calc(var(--ed-orbit-a-web) * var(--orbit-glow))),
      calc(cos(51.43deg - var(--orbit-angle)) * var(--ed-orbit-radius)) calc(sin(51.43deg - var(--orbit-angle)) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-design-glow) / calc(var(--ed-orbit-a-design) * var(--orbit-glow))),
      calc(cos(var(--orbit-angle) + 102.86deg) * var(--ed-orbit-radius)) calc(sin(var(--orbit-angle) + 102.86deg) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-ai-glow) / calc(var(--ed-orbit-a-ai) * var(--orbit-glow))),
      calc(cos(154.29deg - var(--orbit-angle)) * var(--ed-orbit-radius)) calc(sin(154.29deg - var(--orbit-angle)) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-data-glow) / calc(var(--ed-orbit-a-data) * var(--orbit-glow))),
      calc(cos(var(--orbit-angle) + 205.71deg) * var(--ed-orbit-radius)) calc(sin(var(--orbit-angle) + 205.71deg) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-mobile-glow) / calc(var(--ed-orbit-a-mobile) * var(--orbit-glow))),
      calc(cos(257.14deg - var(--orbit-angle)) * var(--ed-orbit-radius)) calc(sin(257.14deg - var(--orbit-angle)) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-practice-growth-glow) / calc(var(--ed-orbit-a-growth) * var(--orbit-glow))),
      calc(cos(var(--orbit-angle) + 308.57deg) * var(--ed-orbit-radius)) calc(sin(var(--orbit-angle) + 308.57deg) * var(--ed-orbit-radius)) var(--ed-orbit-blur) var(--ed-orbit-spread) rgb(var(--ed-cta-glow) / calc(var(--ed-orbit-a-brand) * var(--orbit-glow))),
      var(--ed-card-shadow);
  }
}
.ed-practice:hover,
.ed-practice:focus-within {
  --orbit-glow: 1;
  animation-play-state: running;
}
.ed-practice:hover { transform: translateY(-4px); }

/* AURORA SILK (the owner, 7 October 2026, who lifted "never touch these
 * cards" for it, as for the silk and swell it replaces: that one moved once
 * and stopped, and read too subtle). While the pointer stays on a card, and
 * while its link has keyboard focus, the card's color field flows: its two
 * glows and a third, softer one each run a slow loop of their own (about 8s,
 * never in step: --ed-duration-aurora-a, -b and -c), rising, swaying and
 * twisting like silk or an aurora, in the card's own color, for as long as
 * the pointer stays. On leave every layer glides home from wherever it is
 * and its loop pauses there, so nothing snaps.
 *
 * HOW IT MOVES. Each layer's loop is one registered angle (--aurora-phase)
 * that turns once a period; its pose is the sine and cosine of that angle and
 * of twice it, so each layer traces a closed figure of its own. Every term is
 * multiplied by --aurora, a registered number that eases to 1 on hover or
 * focus and back to 0 on leave, and at 0 a layer is exactly at rest whatever
 * its phase: that is how a loop that never ends still settles smoothly.
 *
 * ONLY TRANSFORM AND OPACITY CHANGE, on three pseudo-elements, each its own
 * compositor layer while it shows (will-change), so nothing is repainted per
 * frame: no background-position moves and no filter runs; the softness is in
 * the gradients' own stops. Hidden at rest, the layers paint nothing and hold
 * no compositor layer.
 *
 * AT REST THE CARD IS UNTOUCHED: its glows are its own background, as drawn,
 * and the three layers are hidden. On hover or focus the first two layers
 * each take one of the card's two gradients (`inherit`: the same values,
 * never a copy) and show at --aurora 0, exactly where the background drew
 * them, and the card stops painting its own (background-size 0); the third
 * fades in from nothing. On leave the swap back waits for the layers to
 * settle (--ed-duration-aurora-settle), so it cannot be seen.
 *
 * THE EDGES NEVER SHOW. The two drawn glows are the card's size and are
 * strongest on its bottom edge, so each grows from its own center on that
 * edge (transform-origin): it stretches upward and across, never below its
 * drawn size, and the color along the bottom edge stays put. It sways and
 * leans only toward the side where its gradient has already faded to
 * nothing (the first glow's color ends at 84% of the width on the bottom
 * edge, the second's starts at 17%), so the strip a layer uncovers is one it
 * never painted. The third glow fades to nothing well inside its own box,
 * so it can bloom, wander, climb and turn freely. All three
 * sit under the content (z-index -1 in the card's stacking context): the
 * second glow, the third, then the first on top, the drawn two in the
 * background's order. Not mirrored under Arabic: the glows are not.
 *
 * THE THIRD GLOW LIVES ON THE CARD'S SPACER, the empty strip under its
 * content (aria-hidden), placed against the card, so the card's markup is
 * still the design's, node for node.
 *
 * NOTHING CHANGES ON A TOUCH SCREEN, where there is no hover, or for a reader
 * who asked for less motion: the layers never show. The colors, the orbit
 * glow, the radius, the layout, the link and the rail are as they were.
 * KEYBOARD FOCUS ANSWERS ON EVERY SCREEN, an iPad with a keyboard included
 * (the owner, 7 October 2026: focus never waits for hover, layout.css
 * "Focus"), so its half sits outside the hover gate, behind the
 * reduced-motion gate alone; a tap never matches :focus-visible, so a touch
 * screen's tap still changes nothing. The loop's copies of the cards
 * (js/home.js) are inert, so they never take hover or focus. */
@property --aurora { syntax: "<number>"; inherits: false; initial-value: 0; }
@property --aurora-phase { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
@keyframes ed-aurora { to { --aurora-phase: 360deg; } }
.ed-practice::before,
.ed-practice::after,
.ed-practice__spacer::before {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  will-change: transform;
  --aurora: 0;
  animation: ed-aurora var(--aurora-period) linear infinite paused;
  transition: --aurora var(--ed-duration-aurora-settle) var(--ed-ease),
              visibility 0s linear var(--ed-duration-aurora-settle);
}
/* The two drawn glows, each swaying toward its own side (--aurora-side). */
.ed-practice::before,
.ed-practice::after {
  inset: 0;
  background-image: inherit;
  translate: calc(var(--aurora) * var(--aurora-side) * var(--ed-aurora-drift) * (1 - cos(var(--aurora-phase))) / 2) 0;
  scale: calc(1 + var(--aurora) * var(--ed-aurora-spread) * (1 - cos(2 * var(--aurora-phase))) / 2)
         calc(1 + var(--aurora) * (var(--ed-aurora-rise) + var(--ed-aurora-wave) * sin(2 * var(--aurora-phase))));
  transform: skewX(calc(var(--aurora) * -1 * var(--aurora-side) * var(--ed-aurora-lean) * (1 - cos(var(--aurora-phase) + 120deg)) / 2));
}
.ed-practice::after {
  --aurora-side: -1;
  --aurora-period: var(--ed-duration-aurora-a);
  background-size: 100% 100%, 0 0;
  transform-origin: 18% 100%;
}
.ed-practice::before {
  --aurora-side: 1;
  --aurora-period: var(--ed-duration-aurora-b);
  background-size: 0 0, 100% 100%;
  transform-origin: 74% 100%;
}
/* The third, softer glow: the card's color at --ed-aurora-glow, low in the
 * card between the two, fading to nothing well inside its own box. At rest
 * the box is the card's, so nothing spills past the card for anything to
 * scroll; as it shows it blooms to --ed-aurora-bloom more on every side
 * (`scale` about its center), and it wanders across, climbs and bobs, and
 * turns. */
.ed-practice__spacer::before {
  --aurora-period: var(--ed-duration-aurora-c);
  inset: 0;
  background: radial-gradient(37% 24% at 50% 74%, rgb(var(--pc-glow) / var(--ed-aurora-glow)) 0%, rgb(255 255 255 / 0) 100%);
  will-change: transform, opacity;
  opacity: var(--aurora);
  scale: calc(1 + var(--aurora) * var(--ed-aurora-bloom));
  translate: calc(var(--aurora) * var(--ed-aurora-wander) * sin(var(--aurora-phase)))
             calc(var(--aurora) * -1 * (var(--ed-aurora-climb) + var(--ed-aurora-bob) * (1 - cos(2 * var(--aurora-phase))) / 2));
  rotate: calc(var(--aurora) * var(--ed-aurora-twist) * sin(var(--aurora-phase) + 60deg));
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ed-practice:hover {
    background-size: 0 0;
    transition-delay: 0s;
  }
  .ed-practice:hover::before,
  .ed-practice:hover::after,
  .ed-practice:hover .ed-practice__spacer::before {
    --aurora: 1;
    visibility: visible;
    animation-play-state: running;
    transition: --aurora var(--ed-duration-aurora-in) var(--ed-ease), visibility 0s;
  }
}
/* The same, word for word, for keyboard focus on any screen. */
@media (prefers-reduced-motion: no-preference) {
  .ed-practice:has(.ed-practice__cta:focus-visible) {
    background-size: 0 0;
    transition-delay: 0s;
  }
  .ed-practice:has(.ed-practice__cta:focus-visible)::before,
  .ed-practice:has(.ed-practice__cta:focus-visible)::after,
  .ed-practice:has(.ed-practice__cta:focus-visible) .ed-practice__spacer::before {
    --aurora: 1;
    visibility: visible;
    animation-play-state: running;
    transition: --aurora var(--ed-duration-aurora-in) var(--ed-ease), visibility 0s;
  }
}

/* Each card's colour, exactly as drawn (HOME:817-843, HANDOFF.md "Practice
 * colors (final)", 28 September), in card order: glow, icon, label, and the
 * CTA's darker ink over the glow. Growth's icon is its cyan, its label the
 * text shade; Mobile & XR's and Design & UX's glows are a little softer
 * (0.30 and 0.18), Data's first stop 0.32, as drawn. (Data and Growth
 * swapped colours on 28 September; each glow's strength travelled with its
 * colour.) */
.ed-practice--web {
  --pc-glow: var(--ed-practice-web-glow);
  --pc-icon: var(--ed-practice-web-on-light);
  --pc-label: var(--ed-practice-web-on-light);
  --pc-cta: var(--ed-practice-web-over-glow);
}
.ed-practice--ai {
  --pc-glow: var(--ed-practice-ai-glow);
  --pc-icon: var(--ed-practice-ai-on-light);
  --pc-label: var(--ed-practice-ai-on-light);
  --pc-cta: var(--ed-practice-ai-over-glow);
}
.ed-practice--mobile {
  --pc-glow: var(--ed-practice-mobile-glow);
  --pc-glow-a: 0.3;
  --pc-glow-b: 0.18;
  --pc-icon: var(--ed-practice-mobile-on-light);
  --pc-label: var(--ed-practice-mobile-on-light);
  --pc-cta: var(--ed-practice-mobile-over-glow);
}
.ed-practice--data {
  --pc-glow: var(--ed-practice-data-glow);
  --pc-glow-a: 0.32;
  --pc-icon: var(--ed-practice-data-on-light);
  --pc-label: var(--ed-practice-data-on-light);
  --pc-cta: var(--ed-practice-data-over-glow);
}
.ed-practice--growth {
  --pc-glow: var(--ed-practice-growth-glow);
  --pc-icon: var(--ed-practice-growth);
  --pc-label: var(--ed-practice-growth-on-light);
  --pc-cta: var(--ed-practice-growth-over-glow);
}
.ed-practice--design {
  --pc-glow: var(--ed-practice-design-glow);
  --pc-glow-a: 0.3;
  --pc-glow-b: 0.18;
  --pc-icon: var(--ed-practice-design-on-light);
  --pc-label: var(--ed-practice-design-on-light);
  --pc-cta: var(--ed-practice-design-over-glow);
}

.ed-practice__body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1 1 auto;
  padding: clamp(56px, 4.6vw, 68px) clamp(20px, 1.9vw, 26px) clamp(20px, 1.9vw, 26px);
}
.ed-practice__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.ed-practice__icon { color: var(--pc-icon); }
.ed-practice__num {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  letter-spacing: var(--ed-track-label);
  color: var(--ed-muted);
}
.ed-practice__title {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-card);
  font-weight: var(--ed-weight-bold);
  line-height: 1.12;
  letter-spacing: var(--ed-track-snug);
  color: var(--ed-ink);
}
.ed-practice__label {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-medium);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--pc-label);
}
.ed-practice__text {
  margin: 0;
  font-size: var(--ed-size-small);
  line-height: 1.6;
  color: var(--ed-dek);
}

/* The CTA: the words fold away until the card is hovered or the link is
 * focused, and the boxed arrow nudges (HOME:88-91). 48px tall with its
 * padding and the card's full width, so it is a comfortable target. */
.ed-practice__cta {
  margin-block-start: auto;
  padding-block-start: 14px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--pc-cta);
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-medium);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  text-decoration: none;
}
.ed-practice__cta > span:first-child {
  display: inline-block;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  white-space: nowrap;
  transform: translateX(calc(8px * var(--ed-dir)));
  transition: max-width var(--ed-reveal-words) var(--ed-ease), opacity var(--ed-reveal-fade) ease,
              transform var(--ed-reveal-words) var(--ed-ease);
}
.ed-practice:hover .ed-practice__cta > span:first-child,
.ed-practice__cta:focus-visible > span:first-child {
  max-width: 230px;
  opacity: 1;
  transform: none;
}
.ed-practice__box {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: var(--ed-radius);
  border: 1px solid currentColor;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--ed-reveal-fade) ease, transform var(--ed-reveal-nudge) var(--ed-ease);
}
.ed-practice:hover .ed-practice__box { transform: translateX(calc(3px * var(--ed-dir))); }
.ed-practice__arrow:dir(rtl),
.ed-rail__chev:dir(rtl) { scale: -1 1; }

.ed-practice__spacer { flex: 0 0 auto; height: clamp(28px, 2.6vw, 40px); }

/* The arrow buttons. No progress track since 2 October (the owner: "remove
 * these except <> buttons"; docs/BASELINE.md §5). AT THE TOP RIGHT OF THE
 * SECTION since 4 October (the owner, for this move alone): they end the
 * header's row (layout.css, .ed-split), level with the heading's last line;
 * on a phone the row wraps and they drop under the heading, kept at the
 * right. Up there nothing of the rail reaches over them, so the lift that
 * kept the cards' glow room off their clicks below the rail is gone. */
.ed-rail__buttons {
  display: flex;
  flex: none;
  align-items: center;
  gap: 10px;
  margin-inline-start: auto;
}
/* UNTIL js/home.js CLEARS `hidden`, THE ROW KEEPS ITS PLACE, as drawn: the
 * buttons take their 46px from the first paint, so nothing moves when the
 * script wakes up, but they are invisible, so neither focusable nor
 * announced. Without the script they never show, since they would do
 * nothing. (`display: flex` above beats the UA's [hidden] rule; this says
 * what hidden means here.) */
.ed-rail__buttons[hidden] { display: flex; visibility: hidden; }
.ed-rail__btn {
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: var(--ed-radius);
  border: 1px solid var(--ed-rail-btn-line);
  background: var(--ed-surface);
  color: var(--ed-ink);
  cursor: pointer;
  transition: background var(--ed-transition), color var(--ed-transition),
              border-color var(--ed-transition), transform var(--ed-transition);
}
.ed-rail__btn:hover {
  background: var(--ed-ink);
  color: var(--ed-on-dark);
  border-color: var(--ed-ink);
  transform: translateY(-1px);
}
.ed-rail__btn:active { transform: translateY(0); }

/* ---- Statement slab (HOME:806-822) ------------------------------------
 * In the shared slab frame (layout.css, .ed-slab): only its ground, its
 * glows and its rhythm are its own. */

.ed-statement { --ed-focus: var(--ed-cta); }
.ed-statement__slab {
  isolation: isolate;
  background-image: var(--ed-statement-glow);
  background-color: var(--ed-dark);
}
.ed-statement__media { position: absolute; inset: 0; z-index: 0; }
.ed-statement__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ed-statement__slab::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--ed-statement-overlay);
}
.ed-statement__inner {
  position: relative;
  z-index: 2;
  padding-block: var(--ed-section-y);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(18px, 2vw, 26px);
  text-align: center;
}
/* The shared eyebrow (layout.css, .ed-eyebrow), spaced by the column's gap
 * rather than its own margin, in brand purple on dark at the design's 82%:
 * 4.69:1 at worst, in the magenta glow on a phone. Over a photo it is at
 * full strength, 5.20:1 at worst over a white one, where 82% falls to
 * 4.00:1 (docs/BASELINE.md §5). */
.ed-statement__eyebrow {
  margin: 0;
  color: var(--ed-statement-eyebrow);
}
.ed-statement--photo .ed-statement__eyebrow { color: var(--ed-statement-eyebrow-photo); }
.ed-statement__text {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-statement);
  font-weight: var(--ed-weight-bold);
  line-height: 1.1;
  letter-spacing: -0.028em;
  color: var(--ed-on-dark);
  text-wrap: balance;
}
.ed-statement__hl {
  background: var(--ed-statement-highlight);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.ed-statement--photo .ed-statement__hl { background-image: var(--ed-statement-highlight-photo); }
/* Never lose the words: plain white where text cannot be clipped to a
 * gradient, and the system colour when the reader forces colours. */
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .ed-statement__hl { background: none; color: var(--ed-on-dark); -webkit-text-fill-color: currentColor; }
}
@media (forced-colors: active) {
  .ed-statement__hl { background: none; color: CanvasText; -webkit-text-fill-color: currentColor; }
}
.ed-statement__lede {
  max-width: 640px;
  margin: 0;
  font-size: var(--ed-size-lead-lg);
  line-height: 1.6;
  color: var(--ed-on-dark-86);
  text-wrap: pretty;
}
.ed-statement__actions {
  margin-block-start: 6px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 12px clamp(16px, 1.8vw, 24px);
}

/* ---- Proof (HOME:824-859) --------------------------------------------- */

.ed-proof { background: var(--ed-ground-proof); }

/* The short bottom padding is deliberate: Proof and the outcomes read as
 * one block (HANDOFF.md). */
.ed-proof__inner {
  padding-block: var(--ed-section-y) clamp(24px, 2.4vw, 40px);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(28px, 3.4vw, 60px);
  align-items: start;
}
.ed-proof__title { margin-block-end: 24px; line-height: 1.1; letter-spacing: -0.024em; }

.ed-score {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: clamp(14px, 1.5vw, 22px);
  margin-block-end: 22px;
}
.ed-score__figure {
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-figure-lg);
  font-weight: var(--ed-weight-semibold);
  line-height: 0.9;
  letter-spacing: -0.032em;
  color: var(--ed-cta);
}
.ed-score__by {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: clamp(10px, 1vw, 14px);
}
.ed-score__label {
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-title-sm);
  font-weight: var(--ed-weight-semibold);
  line-height: 1;
  letter-spacing: -0.014em;
  color: var(--ed-ink);
}
.ed-score__dots { display: flex; flex: 0 0 auto; gap: 5px; }
.ed-score__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--ed-cta); }

.ed-proof__lede {
  max-width: 480px;
  margin: 0 0 clamp(22px, 2.4vw, 30px);
  font-size: var(--ed-size-lead);
  line-height: 1.65;
  color: var(--ed-body);
  text-wrap: pretty;
}
.ed-proof__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px clamp(16px, 1.8vw, 24px);
}

.ed-quotes { display: flex; flex-direction: column; gap: clamp(16px, 1.8vw, 22px); }
.ed-quote {
  margin: 0;
  border-block-start: 1px solid var(--ed-rule);
  padding-block-start: clamp(26px, 2.6vw, 36px);
}
.ed-quote__text { margin: 0; }
.ed-quote__text p {
  margin: 0 0 14px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-quote);
  font-weight: var(--ed-weight-regular);
  line-height: 1.48;
  letter-spacing: -0.016em;
  color: var(--ed-ink);
  text-wrap: pretty;
}
/* --ed-sub, not the design's #67676F: below 900px the second credit sits in
 * the corner fade, where #67676F is 4.46:1 at the darkest pixel and #61616A
 * 4.88:1 (docs/BASELINE.md §5). */
.ed-quote__by {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-medium);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-sub);
}

/* ---- Client outcomes and press (HOME:861-905) ------------------------- */

.ed-outcomes { background: var(--ed-ground-outcomes); }
.ed-outcomes__inner { padding-block: clamp(24px, 2.4vw, 40px) clamp(24px, 2.6vw, 40px); }
/* With no press block beneath, the section closes on the usual rhythm. */
.ed-outcomes--solo .ed-outcomes__inner { padding-block-end: var(--ed-section-y); }

.ed-outcomes__intro {
  max-width: var(--ed-lede-maxw);
  margin: 0 0 clamp(20px, 2.2vw, 30px);
  font-size: var(--ed-size-body);
  line-height: 1.65;
  color: var(--ed-dek);
  text-wrap: pretty;
}
/* THREE TESTIMONIALS (HANDOFF.md, 27 September evening): one column below
 * 1100px, three across from there, never 2+1. Each li is a card that turns
 * over (the "Cards that turn over" block below); the grid row stretches it,
 * and the flip passes the height down, so the three share the tallest
 * height and their credits line up. */
.ed-outcomes__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 1.5vw, 20px);
}
@media (min-width: 68.75em) {
  .ed-outcomes__row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* The face is the one card surface and its lift (layout.css, .ed-card and
 * .ed-card--lift); only its layout is its own. 14px between the credit and
 * the link, the design's 4px gap and 10px margin. */
.ed-outcome__face {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: clamp(22px, 2.3vw, 30px);
}
.ed-outcome__figure {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1 1 auto;
  margin: 0;
}
/* The mark sits 6px above the words, inside the blockquote and hidden from
 * screen readers, as Proof's marks are. */
.ed-outcome__quote { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.ed-outcome__mark {
  display: block;
  block-size: 26px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-quote-mark);
  font-weight: var(--ed-weight-bold);
  line-height: 1;
  color: var(--ed-quote-mark);
}
.ed-outcome__quote p {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-quote);
  font-weight: var(--ed-weight-medium);
  line-height: 1.45;
  letter-spacing: -0.012em;
  color: var(--ed-ink);
  text-wrap: pretty;
}
.ed-outcome__body {
  margin: 0;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-dek);
  text-wrap: pretty;
}
/* The credit at the foot of the card, 20px under the copy at the least, as
 * drawn; no rule over it since the 28 September night delivery. */
.ed-outcome__by {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-block-start: auto;
  padding-block-start: 20px;
}
/* The credit is in Archivo: the design sets no family on it, so it takes
 * the page's, where the build's body text is IBM Plex Sans. */
.ed-outcome__role,
.ed-outcome__meta { font-family: var(--ed-font-display); }
.ed-outcome__role {
  font-size: var(--ed-size-body);
  font-weight: var(--ed-weight-semibold);
  line-height: 1.4;
  color: var(--ed-ink);
}
/* The design's #67676F on the white card: 5.61:1. */
.ed-outcome__meta {
  font-size: var(--ed-size-caption);
  line-height: 1.5;
  color: var(--ed-muted);
}
.ed-press__wrap { padding-block-end: var(--ed-section-y); }
/* WHERE WE GET QUOTED (HANDOFF.md, 28 September): one light strip in the
 * card material, 24px corners and a soft shadow; below 900px the parts
 * stack. */
.ed-press {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  align-items: center;
  padding: clamp(20px, 2.2vw, 28px) clamp(20px, 2.4vw, 32px);
  background: var(--ed-surface);
  border: 1px solid var(--ed-border);
  border-radius: var(--ed-radius-press);
  box-shadow: var(--ed-press-shadow);
}
@media (min-width: 56.25em) {
  .ed-press { grid-template-columns: auto minmax(0, 1fr) auto; gap: clamp(18px, 2vw, 28px); }
}
.ed-press__head { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ed-press__label {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-eyebrow);
  font-weight: var(--ed-weight-medium);
  letter-spacing: var(--ed-track-eyebrow);
  text-transform: uppercase;
  color: var(--ed-magenta);
}
.ed-press__link { align-self: flex-start; white-space: nowrap; }
.ed-press__rail {
  min-width: 0;
  padding: 2px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Snap to the tiles' edge, not the padding's, so the rail opens at 0. */
  scroll-padding-inline: 2px;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, black 0%, black 88%, transparent 100%);
  mask-image: linear-gradient(90deg, black 0%, black 88%, transparent 100%);
}
.ed-press__rail:dir(rtl) {
  -webkit-mask-image: linear-gradient(270deg, black 0%, black 88%, transparent 100%);
  mask-image: linear-gradient(270deg, black 0%, black 88%, transparent 100%);
}
.ed-press__rail::-webkit-scrollbar { display: none; }
.ed-press__rail:focus-visible { outline: 2px solid var(--ed-link); outline-offset: 4px; border-radius: var(--ed-radius-press-ring); }
.ed-press__tiles { display: flex; gap: 14px; margin: 0; padding: 0; list-style: none; }
.ed-press__tile {
  flex: 0 0 clamp(168px, 15vw, 212px);
  height: clamp(80px, 7vw, 100px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 18px;
  scroll-snap-align: start;
  background: var(--ed-surface);
  border: 1px solid var(--ed-border);
  border-radius: var(--ed-radius-press-tile);
}
.ed-press__logo { width: 100%; height: 100%; object-fit: contain; }
/* The What we do cards' button shape, round, filling royal blue on hover
 * and focus (HANDOFF.md: "46px outline circles"). */
.ed-press__nav { display: flex; gap: 12px; }
.ed-press__nav[hidden] { display: none; }
.ed-press__btn {
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--ed-rail-btn-line);
  border-radius: 50%;
  background: var(--ed-surface);
  color: var(--ed-ink);
  cursor: pointer;
  transition: background var(--ed-transition), color var(--ed-transition),
              border-color var(--ed-transition), transform var(--ed-transition);
}
.ed-press__btn:hover,
.ed-press__btn:focus-visible {
  background: var(--ed-blue);
  color: var(--ed-on-dark);
  border-color: var(--ed-blue);
  transform: translateY(-1px);
}
.ed-press__btn:focus-visible { outline: 2px solid var(--ed-blue); outline-offset: 2px; }
.ed-press__btn[aria-disabled="true"] { color: var(--ed-rail-btn-disabled); cursor: default; }
.ed-press__chev { display: block; }
.ed-press__chev:dir(rtl) { scale: -1 1; }

/* ---- Assessment slab and sample document (HOME:907-973) ---------------
 * In the shared slab frame (layout.css, .ed-slab), with the shared eyebrow
 * and pills: only its ground, its glow and its rhythm are its own. */

.ed-offer { --ed-focus: var(--ed-cta); }
.ed-offer__slab {
  background-image: var(--ed-offer-glow);
  background-color: var(--ed-offer-ground);
}
.ed-offer__slab:dir(rtl) { background-image: var(--ed-offer-glow-rtl); }
.ed-offer__inner { padding-block: var(--ed-section-y); }
.ed-offer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: center;
}
.ed-offer__title {
  margin: 0 0 18px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-h2);
  font-weight: var(--ed-weight-bold);
  line-height: 1.08;
  letter-spacing: var(--ed-track-tight);
  color: var(--ed-on-dark);
  text-wrap: balance;
}
.ed-offer__lede {
  max-width: 600px;
  margin: 0 0 clamp(24px, 2.6vw, 32px);
  font-size: var(--ed-size-lead);
  line-height: 1.65;
  color: var(--ed-on-dark-86);
  text-wrap: pretty;
}
/* Two filled pills as drawn on 1 October, the second the small one, each
 * wrapping its label inside the pill rather than out of the slab (with
 * larger browser text at 320px). */
.ed-offer__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

/* THE STEP ROWS (HANDOFF.md, "Step rows", 28 September): no hairlines; a
 * grid of number, title and description, so every description starts on
 * the same line; below 760px the description stacks under the title, in
 * the title's column. Number mono 12px white, title 16-18px, description
 * Plex Sans 15px at 86% white.
 *
 * AND AGAIN FROM 900 TO 999px, beside the sample document, where three
 * columns as drawn squeeze each description to 82-167px (the owner's call,
 * docs/BASELINE.md §5); three columns again from 1000px. */
.ed-offer__steps {
  margin-block-start: clamp(22px, 2.2vw, 30px);
  display: flex;
  flex-direction: column;
}
.ed-offer__step {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  column-gap: 14px;
  row-gap: 6px;
  align-items: baseline;
  padding-block: 12px;
}
.ed-offer__num {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-eyebrow);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  color: var(--ed-on-dark);
}
.ed-offer__step-title {
  min-width: 0;
  overflow-wrap: break-word;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-step);
  font-weight: var(--ed-weight-bold);
  letter-spacing: -0.016em;
  color: var(--ed-on-dark);
}
.ed-offer__step-text {
  grid-column: 2;
  min-width: 0;
  font-family: var(--ed-font-body);
  font-size: var(--ed-size-body);
  line-height: 1.55;
  color: var(--ed-on-dark-86);
  text-wrap: pretty;
}
@media (min-width: 47.5em) and (max-width: 56.1875em), (min-width: 62.5em) {
  .ed-offer__step { grid-template-columns: 28px minmax(0, 240px) minmax(0, 1fr); }
  .ed-offer__step-text { grid-column: auto; }
}

.ed-doc-figure { margin: 0; width: 100%; }
/* THE SAMPLE TILTS ON HOVER like a sheet of paper (HANDOFF.md, "Sample
 * assessment hover", 28 September, night): it leans back and lifts 4px in
 * the flip cards' depth, and its shadow draws in, over 0.5s. Any pointer, as
 * drawn. Reduced motion keeps the shadow and never tilts. */
.ed-doc {
  background: var(--ed-doc-ground);
  border: 1px solid var(--ed-doc-edge);
  border-radius: var(--ed-radius-doc);
  overflow: hidden;
  box-shadow: var(--ed-doc-shadow);
  transform-origin: 50% 60%;
  transition: transform var(--ed-duration-tilt) var(--ed-ease), box-shadow var(--ed-duration-tilt) ease;
}
.ed-doc:hover { box-shadow: var(--ed-doc-shadow-hover); }
@media (prefers-reduced-motion: no-preference) {
  .ed-doc:hover { transform: perspective(var(--ed-perspective)) rotateX(3deg) rotateY(-4deg) translateY(-4px); }
}
.ed-doc__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px clamp(16px, 1.6vw, 22px);
  background: var(--ed-doc-head);
  border-block-end: 1px solid var(--ed-hairline-on-dark);
}
.ed-doc__name,
.ed-doc__tag {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
}
.ed-doc__name { color: var(--ed-on-dark); }
.ed-doc__tag {
  flex: 0 0 auto;
  padding: 3px 7px;
  border-radius: var(--ed-radius-label);
  background: var(--ed-cta);
  color: var(--ed-on-brand);
}
.ed-doc__block {
  margin: 0;
  padding: 15px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ed-doc__meta { gap: 6px; }
.ed-doc__block--tight { gap: 9px; }
.ed-doc__rule { border-block-start: 1px solid var(--ed-hairline-on-dark); }
.ed-doc__pair { display: flex; justify-content: space-between; gap: 10px; }
.ed-doc__key {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-eyebrow);
  text-transform: uppercase;
  color: var(--ed-on-dark-58);
}
.ed-doc__value {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  color: var(--ed-doc-ink-value);
}
.ed-doc__value--accent { color: var(--ed-on-dark); }
.ed-doc__text {
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-caption);
  line-height: 1.5;
  color: var(--ed-doc-ink);
}
.ed-doc__findings { display: flex; flex-direction: column; gap: 10px; }
/* Only the findings wrap "pretty", as drawn; the risks and the phase names
 * wrap plainly. */
.ed-doc__findings .ed-doc__text { text-wrap: pretty; }
.ed-doc__finding { display: flex; gap: 10px; }
.ed-doc__fnum {
  flex: 0 0 auto;
  padding-block-start: 1px;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  color: var(--ed-on-dark);
}
.ed-doc__risks { margin: 0; display: flex; flex-direction: column; gap: 9px; }
.ed-doc__risk { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.ed-doc__risk .ed-doc__text { line-height: 1.45; }
.ed-doc__level {
  flex: 0 0 auto;
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ed-on-dark-50);
}
.ed-doc__level--high { color: var(--ed-on-dark); }

/* THE PHASE PLAN, A TABLE IN THE DESIGN'S FLEX ROWS: 9px between rows, the
 * header's two labels at either end, and in each row the number, the name
 * taking the room, the duration and the cost bar 12px apart, the bar giving
 * way first on a narrow phone, as drawn. Its roles keep it a table for a
 * screen reader (assessment.html). */
.ed-doc__plan,
.ed-doc__plan thead,
.ed-doc__plan tbody { display: flex; flex-direction: column; gap: 9px; }
.ed-doc__plan tr { display: flex; align-items: center; gap: 12px; }
.ed-doc__plan thead tr { justify-content: space-between; gap: 10px; }
.ed-doc__plan th {
  padding: 0;
  font-weight: var(--ed-weight-semibold);
  text-align: start;
}
.ed-doc__plan .ed-doc__th-cost { text-align: end; }
.ed-doc__plan td { padding: 0; }
.ed-doc__pnum,
.ed-doc__dur { flex: 0 0 auto; }
.ed-doc__pnum {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  color: var(--ed-doc-ink-faint);
}
.ed-doc__pname { flex: 1 1 auto; line-height: 1.4; }
.ed-doc__dur {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  color: var(--ed-on-dark-55);
}
.ed-doc__cost { display: flex; flex: 0 1 auto; min-width: 0; }

/* The redaction bars, at the design's four widths. */
.ed-redact {
  display: inline-block;
  height: 11px;
  border-radius: var(--ed-radius-redact);
  background: var(--ed-doc-redact);
  vertical-align: -1px;
}
.ed-redact--xl { width: 86px; }
.ed-redact--l { width: 72px; }
.ed-redact--m { width: 56px; }
.ed-redact--s { width: 48px; }

.ed-doc-figure__caption {
  margin-block-start: 11px;
  padding-inline-start: 2px;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  line-height: 1.55;
  letter-spacing: 0.06em;
  color: var(--ed-on-dark-58);
}

/* ---- How we work (HOME:975-1016) -------------------------------------- */

.ed-how { background: var(--ed-ground-how); }
.ed-how__head { max-width: var(--ed-head-maxw); margin-block-end: clamp(24px, 2.8vw, 42px); }
.ed-how__title { max-width: var(--ed-head-maxw); }
.ed-how__lede { max-width: var(--ed-lede-maxw); margin-block-start: 18px; }
/* THE INDEX LIST (the owner, 3 October; the design draws six dark cards):
 * one full-width row per commitment between hairlines, the number, title
 * and text on one line from a tablet up, the text under the number and
 * title on a phone. The numbers are the pillars' purple mono, so the page's
 * two numbered lists read as one family. */
.ed-index {
  margin-block-start: clamp(28px, 3.4vw, 48px);
  border-block-end: 1px solid var(--ed-rule);
}
.ed-index__row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 8px 16px;
  align-items: baseline;
  padding-block: clamp(18px, 2vw, 28px);
  border-block-start: 1px solid var(--ed-rule);
}
.ed-index__num {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.15em;
  color: var(--ed-purple);
  transition: transform var(--ed-wipe-duration) var(--ed-ease);
}
/* A ROW ANSWERS THE POINTER (the owner, 4 October: "Hover and focus: the How
 * we work index rows"): the hairline above it turns brand purple, the hover
 * color, wiping in from the inline start as the menus' hover underline
 * does (its thickness, duration and ease), and the number steps forward
 * 4px. Transform only, nothing reflows. The rows hold no link and take no
 * focus, so there is no keyboard focus to answer; and since a row does
 * nothing when pressed, its title never lights up as a link would. Never on
 * a touch screen, where a tap would leave it lit; for a reader who asked
 * for less motion the line shows without wiping and the number stays. */
.ed-index__row::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-start: -1px;
  block-size: var(--ed-wipe-thickness);
  background: var(--ed-purple);
  transform: scaleX(0);
  transform-origin: 0 0;
  transition: transform var(--ed-wipe-duration) var(--ed-ease-wipe);
  pointer-events: none;
}
.ed-index__row:dir(rtl)::before { transform-origin: 100% 0; }
@media (hover: hover) {
  .ed-index__row:hover::before { transform: none; }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ed-index__row:hover .ed-index__num { transform: translateX(calc(var(--ed-nudge) * var(--ed-dir))); }
}
.ed-index__title {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-card-title);
  font-weight: var(--ed-weight-bold);
  line-height: 1.2;
  letter-spacing: -0.018em;
  color: var(--ed-ink);
}
.ed-index__text {
  grid-column: 1 / -1;
  margin: 0;
  max-width: 68ch;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-body);
  text-wrap: pretty;
}

/* ---- Industries ledger (HOME:1018-1042) -------------------------------- */

.ed-industries { background: var(--ed-ground-industries); }
.ed-ledger {
  display: grid;
  gap: clamp(24px, 3vw, 44px);
}
.ed-ledger__title { line-height: 1.14; letter-spacing: -0.02em; }
.ed-ledger__lede { max-width: var(--ed-lede-maxw); margin-block-start: 18px; }
/* 20px above the text as drawn (HOME: margin-top:20px). */
.ed-ledger__link { margin-block-start: 20px; }

/* THE SECTORS' TILES. THE CHOSEN ONE IS THE PLUM with the brand glow and
 * white words: a cue in lightness as well as colour (white words on the plum
 * against ink on white). NO MAGENTA EDGE on any tile since 4 October (the
 * owner: "remove the magenta edge"). */
.ed-sectors__tab {
  background: var(--ed-surface);
  border: 1px solid var(--ed-rule);
  border-radius: var(--ed-radius-tile);
  color: var(--ed-ink);
}
.ed-sectors__tab:hover { border-color: var(--ed-link); }
.ed-sectors__tab:hover .ed-tab__name { color: var(--ed-link); }
.ed-sectors__tab[aria-selected="true"] {
  background-color: var(--ed-dark-plum);
  background-image: var(--ed-sector-glow);
  border-color: var(--ed-dark-plum);
  color: var(--ed-on-dark);
}
.ed-sectors__tab[aria-selected="true"]:dir(rtl) { background-image: var(--ed-sector-glow-rtl); }
.ed-sectors__tab[aria-selected="true"] .ed-tab__num { color: var(--ed-purple-on-dark); }
.ed-sectors__tab[aria-selected="true"] .ed-tab__name { color: var(--ed-on-dark); }

/* THE SECTORS AS VERTICAL TABS (the owner, 3 October; the design draws rows
 * that open). On a phone the shared tab row above the panel; from a tablet up
 * the tiles stand on the left and the panel on the right ("Wider screens").
 * The text is in Archivo, as drawn. */
.ed-sectors {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 1.6vw, 24px);
  align-items: start;
  font-family: var(--ed-font-display);
}
.ed-sectors__sub { display: none; }
.ed-sectors__panels { display: grid; gap: 16px; min-width: 0; }
.ed-sector {
  display: grid;
  align-content: start;
  min-width: 0;
  padding: clamp(20px, 2.4vw, 32px);
  background: var(--ed-surface);
  border: 1px solid var(--ed-rule);
  border-radius: var(--ed-radius-card);
}
/* The display above would otherwise beat the hidden attribute. */
.ed-sector[hidden] { display: none; }
/* Once they are tabs the panels share one grid cell, so a crossfade has
 * both in place (js/home.js). */
.ed-sectors[data-tabs-ready] .ed-sectors__panels > .ed-sector { grid-area: 1 / 1; }
.ed-sector:focus-visible { outline-offset: 4px; }
/* THE PANEL'S HEAD: the sector's heading and "Start a consultation" (the
 * owner, 4 October), the button under the heading on a phone and at the top
 * right beside it from a tablet up ("Wider screens"), where a long heading
 * wraps rather than push the button out. */
.ed-sector__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  margin-block-end: 12px;
}
.ed-sector__cta { flex: none; }
.ed-sector__title {
  margin: 0;
  font-size: var(--ed-size-card-title);
  font-weight: var(--ed-weight-bold);
  line-height: 1.2;
  letter-spacing: -0.018em;
  color: var(--ed-ink);
}
.ed-sector__text {
  margin: 0 0 18px;
  max-width: 68ch;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-body);
  text-wrap: pretty;
}
.ed-sector__text:last-child { margin-block-end: 0; }
.ed-ledger__how {
  margin: 0 0 10px;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-card-label);
}
.ed-ledger__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ed-ledger__list li {
  display: flex;
  gap: 10px;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-dek);
}
/* The dot, 6px and purple, level with the first line. */
.ed-ledger__list li::before {
  content: "";
  flex: 0 0 auto;
  inline-size: var(--ed-dot-size);
  block-size: var(--ed-dot-size);
  margin-block-start: 9px;
  border-radius: 50%;
  background: var(--ed-link);
}
/* WHERE IT SHOWS UP: one white tile per named industry, six to a row, in
 * one, two or three columns so every line of tiles is full: two from 560px
 * and three from 1000px ("Wider screens", below). The design's own sizes:
 * the name 14px, the pressure 13px. */
.ed-ledger__how--places { margin-block: 18px 10px; }
.ed-ledger__places {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ed-ledger__place {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  background: var(--ed-bg-alt);
  border: 1px solid var(--ed-border);
  border-radius: var(--ed-radius-tile);
}
.ed-ledger__place-name {
  font-size: var(--ed-size-small);
  font-weight: var(--ed-weight-semibold);
  color: var(--ed-ink);
}
.ed-ledger__place-text {
  font-size: var(--ed-size-caption);
  line-height: 1.5;
  color: var(--ed-faint);
}

/* ---- Technology slab (HOME:1043-1130) ----------------------------------
 * In the shared slab frame (layout.css, .ed-slab), with the shared eyebrow:
 * only its ground, its mesh, its spotlight and its rhythm are its own. */

.ed-stack { --ed-focus: var(--ed-label-on-dark); }
.ed-stack__slab {
  background-image: var(--ed-stack-mesh);
  background-color: var(--ed-stack-ground);
}
.ed-stack__inner {
  position: relative;
  padding-block: var(--ed-section-y);
}
/* The pointer spotlight. js/home.js writes --mx and --my on hover-capable
 * devices; until it does, the light sits off the slab. The content above it
 * is positioned so it paints over the light, never under it.
 *
 * ON THE SLAB, EDGE TO EDGE, not on the content column inside it: there the
 * light stopped dead at the column's edge, a hard line about 130px in from
 * the slab's side on a wide screen (the owner, 26 September: "should work for
 * full bleed full width"). The slab clips it to its rounded corners. */
.ed-stack__slab::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(var(--ed-stack-spot-size) circle at var(--mx, -999px) var(--my, -999px), var(--ed-stack-spot), transparent 68%);
}
.ed-stack__head,
.ed-stack__layers,
.ed-stack__commits { position: relative; }

.ed-stack__head {
  gap: clamp(18px, 3vw, 56px);
  align-items: end;
  margin-block-end: clamp(26px, 2.9vw, 42px);
}
.ed-stack__title {
  max-width: 520px;
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-h2);
  font-weight: var(--ed-weight-bold);
  line-height: 1.06;
  letter-spacing: -0.028em;
  color: var(--ed-on-dark);
  text-wrap: balance;
}
.ed-stack__intro { display: flex; flex-direction: column; gap: 14px; max-width: 560px; }
.ed-stack__lede {
  margin: 0;
  font-size: var(--ed-size-lead);
  line-height: 1.6;
  color: var(--ed-on-dark-86);
  text-wrap: pretty;
}
.ed-stack__meta {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-medium);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-on-dark-55);
}

.ed-stack__layers {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(20px, 2.2vw, 34px);
  align-items: start;
}
.ed-stack__commits {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(18px, 2.2vw, 36px);
  margin: clamp(26px, 2.8vw, 42px) 0 0;
}
/* NO HAIRLINE ABOVE A COMMITMENT (the owner, 4 October 2026): Maintenance,
 * Upgrades and Ownership stand on the slab under the layers, with only the
 * space above them to set them apart; the layers keep their own lines. */
.ed-stack__commit {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 240px;
  min-width: 0;
}
/* A label inside a card on dark (--ed-card-label-on-dark): 5.91:1 at worst,
 * with the spotlight on it. A linked commitment is the underlined white text
 * link (layout.css, .ed-textlink--underline). */
.ed-stack__commit-label {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ed-card-label-on-dark);
}
.ed-stack__commit-text {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-body);
  line-height: 1.55;
  color: var(--ed-on-dark-90);
}

/* ---- Engagement models (HOME:1132-1174) -------------------------------- */

.ed-engage { background: var(--ed-ground-engage); }
.ed-engage__head { max-width: var(--ed-head-maxw); margin-block-end: clamp(20px, 2.1vw, 30px); }
.ed-engage__lede { max-width: var(--ed-lede-maxw); margin-block-start: 18px; }
.ed-engage__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 1.5vw, 20px);
  margin-block-start: clamp(28px, 3.4vw, 48px);
}
.ed-model {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  padding: clamp(22px, 2.2vw, 28px);
  background: var(--ed-surface);
  border: 1px solid var(--ed-border);
  border-radius: var(--ed-radius-card);
  box-shadow: var(--ed-model-shadow);
  transition: border-color var(--ed-duration-card) ease, box-shadow var(--ed-duration-card) ease;
}
.ed-model:hover { border-color: var(--ed-purple); box-shadow: var(--ed-model-shadow-hover); }
.ed-model--featured { border-color: var(--ed-purple); }
/* The featured card's badge: a dot-led tag (layout.css, .ed-tag), never a
 * pill (HANDOFF.md, "Tags and badges"), in the tag's purple ink. */
.ed-model__badge {
  align-self: flex-start;
  margin: 0 0 2px;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-tag-ink);
}
.ed-model__title {
  margin: 6px 0 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-card-title);
  font-weight: var(--ed-weight-bold);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--ed-ink);
}
/* A label inside a card, in its royal blue role (--ed-card-label): 7.32:1
 * on the white card. A <div>, as drawn, so it wraps plainly. */
.ed-model__meta {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ed-card-label);
}
.ed-model__body { margin: 0; font-size: var(--ed-size-body); line-height: 1.6; color: var(--ed-dek); }

/* ---- Cards that turn over (HOME:46-61; HANDOFF.md, "Flip affordance") ---
 * The outcome cards and the engagement models. Each is a 3D card: both faces
 * share one grid cell, so the card is as tall as its taller face and nothing
 * moves when it turns. The back is always in the markup and invisible until
 * the card is turned (visibility, so it is neither focusable nor announced);
 * js/home.js does the turning, makes the front's link the button that turns
 * it, and marks the card data-flip-ready. Without the script the card is a
 * plain card whose link goes to the form. */
.ed-flip__back {
  --ed-focus: var(--ed-label-on-dark);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: clamp(22px, 2.3vw, 30px);
  /* Transparent, so forced-colours mode draws the card's edge. An outline
   * inside the edge, not a border: the design's back has none, and a border
   * took 1px off every side of the content. */
  outline: 1px solid transparent;
  outline-offset: -1px;
  border-radius: var(--ed-radius-card);
  background: var(--ed-flip-back-glow), var(--ed-flip-back-ground);
  box-shadow: var(--ed-flip-back-shadow);
  color: var(--ed-on-dark);
  transform: rotateY(180deg);
  visibility: hidden;
  transition: visibility 0s linear var(--ed-flip-hide-delay);
}
.ed-flip__back:dir(rtl) { background: var(--ed-flip-back-glow-rtl), var(--ed-flip-back-ground); }
.ed-flip { display: grid; min-width: 0; perspective: var(--ed-perspective); }
.ed-flip__in {
  display: grid;
  transform-style: preserve-3d;
  transition: transform var(--ed-duration-flip) var(--ed-ease);
}
.ed-flip__face,
.ed-flip__back {
  grid-area: 1 / 1;
  min-width: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.ed-flip[data-on="true"] > .ed-flip__in { transform: rotateY(180deg); }
.ed-flip[data-on="true"] .ed-flip__back { visibility: visible; transition-delay: 0s; }
.ed-flip[data-flip-ready] .ed-flip__face { cursor: pointer; }
/* THE PEEK: a card that can turn tilts on hover, so it reads as two-sided,
 * and lifts as the other cards do: --ed-flip-tilt (12deg, the owner, 4
 * October; the design draws 7deg) and --ed-flip-lift (4px), over the turn's
 * own duration; mirrored under Arabic. Never for a reader who asked for
 * less motion, and never on a touch screen; turning over is still a click
 * or a tap. The lift is the turning layer's, so the hovered card itself
 * never moves out from under the pointer; a face that lifts on its own (the
 * testimonials' card surface, .ed-card--lift) keeps its shadow and edge and
 * gives up its own 4px here, so no card rises 8px. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ed-flip[data-flip-ready]:not([data-on="true"]):hover > .ed-flip__in {
    transform: translateY(calc(-1 * var(--ed-flip-lift))) rotateY(calc(-1 * var(--ed-flip-tilt)));
  }
  .ed-flip[data-flip-ready]:not([data-on="true"]):dir(rtl):hover > .ed-flip__in {
    transform: translateY(calc(-1 * var(--ed-flip-lift))) rotateY(var(--ed-flip-tilt));
  }
  .ed-flip[data-flip-ready]:not([data-on="true"]):hover > .ed-flip__in > .ed-card--lift { transform: none; }
}

/* The link on the front that turns the card: the shared text link
 * (layout.css, .ed-link), the same as an <a> before the script and a
 * <button> after it. Its box is its line, 19px of IBM Plex Sans, so the ring
 * hugs it, and its 44px target is the shared hit area, kept inside the
 * turning card by the link's position: relative. Here only what a button
 * resets, the forward arrow 6px on, and the design's quicker fade for the
 * flip controls. */
.ed-flip__open {
  align-self: flex-start;
  gap: 6px;
  padding: 0;
  border: 0;
  background: none;
  text-align: start;
  cursor: pointer;
  transition: color var(--ed-transition-quick);
}
.ed-flip__rarr:dir(rtl),
.ed-flip__larr:dir(rtl) { scale: -1 1; }
/* Their arrows step --ed-nudge the way they point on hover and keyboard
 * focus, as every standalone link's does (layout.css, "Text links"):
 * plainly, since the mirror above turns the step round under Arabic. The
 * hover step never on a touch screen; the keyboard's on every screen
 * (layout.css, "Focus"). */
.ed-flip__rarr,
.ed-flip__larr { transition: transform var(--ed-duration-slide) var(--ed-ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ed-link:hover > .ed-flip__rarr { transform: translateX(var(--ed-nudge)); }
  .ed-textlink:hover > .ed-flip__larr { transform: translateX(calc(-1 * var(--ed-nudge))); }
}
@media (prefers-reduced-motion: no-preference) {
  .ed-link:focus-visible > .ed-flip__rarr { transform: translateX(var(--ed-nudge)); }
  .ed-textlink:focus-visible > .ed-flip__larr { transform: translateX(calc(-1 * var(--ed-nudge))); }
}
/* "Discuss this model" at the foot of the card, 6px under the copy at the
 * least, as drawn. After the rule above, so its padding is the one that
 * applies. */
.ed-model__flip { margin-block-start: auto; padding-block-start: 6px; }

/* "Next step" on every back, a label inside a card on dark
 * (--ed-card-label-on-dark): 7.74:1 on #0A0910, 6.23:1 at the glow's peak. */
.ed-flip__eyebrow {
  margin: 0;
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-label);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: var(--ed-track-label);
  text-transform: uppercase;
  color: var(--ed-card-label-on-dark);
}
.ed-flip__title {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-card-title);
  font-weight: var(--ed-weight-bold);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ed-on-dark);
  text-wrap: balance;
}
.ed-flip__text {
  margin: 0;
  font-size: var(--ed-size-body);
  line-height: 1.6;
  color: var(--ed-on-dark-86);
  text-wrap: pretty;
}
.ed-flip__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  margin-block-start: 8px;
}
/* The pill is the shared small one, wrapping a long label inside itself
 * (.ed-btn--sm, .ed-btn--wrap). "Back", 20px under it as drawn, is the
 * shared text link on dark (layout.css, .ed-textlink), its box the line and
 * its 44px target the shared hit area; one space between the arrow and the
 * words, as drawn (0.2em). */
.ed-flip__close {
  gap: 0.2em;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: color var(--ed-transition-quick);
}

/* ---- Insights (HOME:1176-1203) ----------------------------------------- */

.ed-insights { background: var(--ed-ground-insights); }
.ed-insights__head {
  gap: 16px clamp(20px, 3vw, 40px);
  margin-block-end: clamp(20px, 2.1vw, 30px);
}
.ed-insights__head .ed-split__head { max-width: var(--ed-head-maxw); }
/* ---- Contact slab and enquiry form (HOME:1205-1264) --------------------
 * In the shared slab frame (layout.css, .ed-slab), with the shared eyebrow
 * (7.12-7.43:1 on the mesh): only its ground, its mesh and its rhythm are
 * its own. */

.ed-contact { --ed-focus: var(--ed-cta); }
.ed-contact__slab {
  background-image: var(--ed-contact-mesh);
  background-color: var(--ed-slab-ground);
}
.ed-contact__inner {
  padding-block: var(--ed-slab-close-y);
  gap: clamp(24px, 3vw, 48px);
  /* The copy is centred against the form (HANDOFF.md, "Contact slab"). */
  align-items: center;
}
.ed-contact__title {
  margin: 0 0 20px;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-h2);
  font-weight: var(--ed-weight-bold);
  line-height: 1.08;
  letter-spacing: var(--ed-track-tight);
  color: var(--ed-on-dark);
  text-wrap: balance;
}
.ed-contact__lede {
  max-width: 480px;
  margin: 0 0 clamp(26px, 2.8vw, 36px);
  font-size: var(--ed-size-lead);
  line-height: 1.65;
  color: var(--ed-on-dark-90);
}
/* A tight list since 28 September: no hairlines, a 36px number column,
 * 14px between steps (HANDOFF.md, "Step rows"). */
.ed-contact__steps {
  margin-block-end: 26px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ed-contact__step {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  gap: 12px;
  align-items: baseline;
}
.ed-contact__num {
  font-family: var(--ed-font-mono);
  font-size: var(--ed-size-caption);
  font-weight: var(--ed-weight-semibold);
  letter-spacing: 0.08em;
  color: var(--ed-on-dark);
}
.ed-contact__step-text {
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-body);
  line-height: 1.55;
  color: var(--ed-on-dark-90);
}
.ed-contact__note {
  margin: 0;
  font-family: var(--ed-font-display);
  font-size: var(--ed-size-small);
  line-height: 1.55;
  color: var(--ed-on-dark-72);
}
/* The heading's second line, "not a sales call", in the Statement's brand
 * gradient (HANDOFF.md, "Contact slab"), with the same middle stop the
 * Statement takes: the design's #6B21C4 is 2.49:1 here (tokens.css). */
.ed-contact__em {
  background-image: var(--ed-statement-highlight);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
@media (forced-colors: active) {
  .ed-contact__em { color: CanvasText; -webkit-text-fill-color: CanvasText; background: none; }
}

/* THE INQUIRY CARD'S EDGE LIGHT (HANDOFF.md, "Project inquiry glow", 28
 * September): behind the white card, a crisp 2px ring and a blurred halo,
 * both a conic gradient of the brand colours that turns. At rest neither
 * shows and the card has only a faint shadow; hover lights the ring and the
 * halo at 85%, one turn every 8s; a focused field lights both fully, one
 * turn every 3.5s, over the card's own purple focus ring. Reduced motion
 * keeps the light and stops the turn. Decoration only: aria-hidden, and no
 * pointer events. */
@property --glow-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
@keyframes ed-glow-turn { to { --glow-angle: 360deg; } }
.ed-contact .ed-leadform { --lf-base: var(--ed-leadform-rest); z-index: 1; }
.ed-contact .ed-leadform:hover { box-shadow: var(--lf-base); }
.ed-contact .ed-leadform:focus-within { box-shadow: var(--ed-leadform-shadow), var(--ed-leadform-focus); }
.ed-glow { position: relative; isolation: isolate; border-radius: var(--ed-glow-radius); }
.ed-glow__halo,
.ed-glow__ring {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  background: conic-gradient(from var(--glow-angle), var(--ed-cta), var(--ed-purple), var(--ed-blue),
                             var(--ed-purple), var(--ed-magenta), var(--ed-cta));
  opacity: 0;
  transition: opacity var(--ed-glow-fade) ease;
}
.ed-glow__halo {
  inset: var(--ed-glow-halo-inset);
  border-radius: var(--ed-glow-halo-radius);
  filter: blur(var(--ed-glow-blur));
}
.ed-glow__ring { inset: var(--ed-glow-ring-inset); border-radius: var(--ed-glow-radius); }
.ed-glow:hover .ed-glow__halo { opacity: 0.85; animation: ed-glow-turn var(--ed-glow-turn) linear infinite; }
.ed-glow:hover .ed-glow__ring { opacity: 1; animation: ed-glow-turn var(--ed-glow-turn) linear infinite; }
.ed-glow:focus-within .ed-glow__halo,
.ed-glow:focus-within .ed-glow__ring { opacity: 1; animation: ed-glow-turn var(--ed-glow-turn-focus) linear infinite; }
@media (forced-colors: active) {
  .ed-glow__halo,
  .ed-glow__ring { display: none; }
}

/* ---- Wider screens -----------------------------------------------------
 * The design's own breakpoints (HOME:100-130), in ascending order. */

@media (min-width: 35em) {
  .ed-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ed-stack__layers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ed-ledger__places { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 30em) {
  .ed-owners__scale,
  .ed-owners__row { grid-template-columns: minmax(0, 1fr) repeat(3, minmax(0, 5.5rem)); }
  .ed-owners__scale > :first-child { display: block; }
  .ed-owners__row > dt { grid-column: 1; }
  .ed-owner { grid-column: 2 / -1; }
}

/* The three ways' pills share the track evenly: no scrolling. */
@media (min-width: 37.5em) {
  .ed-ways__tabs {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4px;
    overflow: visible;
  }
}

@media (min-width: 40em) {
  .ed-engage__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* From a tablet up: each commitment on one line (number, title, text), and
 * the sector tabs beside their panel. */
@media (min-width: 48em) {
  .ed-index__row { grid-template-columns: 3.5rem minmax(0, 0.9fr) minmax(0, 1.5fr); }
  .ed-index__text { grid-column: auto; }
  /* COMPACT TILES, AND THE PANEL SETS THE HEIGHT (the owner, 4 October: the
   * tall tiles left a large empty space under the panel). Each tile is its
   * number and name on one line, as the Technology layers are, with the
   * industries under them, in less padding and tighter gaps, so the four
   * stand shorter than any group's panel from a tablet up (measured, 768 to
   * 1440: docs/BASELINE.md §5). The list still stretches to the row, and the
   * space left over is shared out evenly, so the tiles end with the panel;
   * each keeps its own height rather than all taking the tallest's, which
   * would cost the 2-line tiles the 3-line tiles' extra line. */
  .ed-sectors { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr); align-items: stretch; }
  .ed-sectors__tabs {
    display: grid;
    gap: 8px;
    margin: 0;
    padding: 0;
    overflow: visible;
  }
  .ed-sectors__tab {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline;
    align-content: start;
    gap: 6px 10px;
    padding: 14px 18px;
    text-align: start;
    white-space: normal;
  }
  .ed-sectors__tab .ed-tab__name { font-size: var(--ed-size-card-title); }
  .ed-sectors__sub {
    display: block;
    grid-column: 1 / -1;
    font-family: var(--ed-font-body);
    font-size: var(--ed-size-caption);
    font-weight: var(--ed-weight-regular);
    line-height: 1.55;
    color: var(--ed-sub);
  }
  .ed-sectors__tab[aria-selected="true"] .ed-sectors__sub { color: var(--ed-on-dark-72); }
  .ed-sector__head {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
  }
  .ed-sector__head > .ed-sector__title { flex: 1 1 auto; min-width: 0; }
}

@media (min-width: 51.25em) {
  .ed-stack__layers { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 56.25em) {
  .ed-proof__inner { grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr); }
  /* SIDE BY SIDE, THE TWO COLUMNS END TOGETHER (the owner, 4 October). On
   * the left the way and what it includes, one under the other; on the right
   * the photograph over who owns what (the owner, 7 October), spanning both
   * rows. The second row takes whatever height is left, so what the way
   * includes follows its description whatever the right column's height.
   * When the left column is the taller, Who owns what stretches to it: its
   * rows share the height evenly, each part of the work and its mark centred
   * in its row, and its last line lies level with the foot of the button. */
  .ed-pillar {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas: "intro side" "includes side";
  }
  .ed-pillar__intro { grid-area: intro; }
  .ed-pillar__includes { grid-area: includes; }
  .ed-pillar__side { grid-area: side; display: flex; flex-direction: column; gap: 22px; }
  .ed-pillar__photo { margin-block-start: 0; }
  .ed-pillar__detail { flex: 1 1 auto; display: flex; flex-direction: column; margin-block-start: 0; }
  .ed-pillar__detail > :first-child { margin-block-start: 0; }
  .ed-pillar__detail > .ed-owners { flex: 1 1 auto; display: flex; flex-direction: column; margin-block-end: 0; }
  .ed-owners__row { flex: 1 1 auto; }
  .ed-offer__grid { grid-template-columns: minmax(0, 1fr) minmax(300px, 400px); }
}

@media (min-width: 62.5em) {
  .ed-engage__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ed-ledger__places { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 68.75em) {
  .ed-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 75em) {
  /* The Technology layers in one row, as drawn: six since the owner's Design
   * row (10 October 2026), where five left it alone on a second row. The
   * widest chip, "visionOS & ARKit", fits a 156px column (measured at 1200,
   * 1280 and 1440px). Two rows of three below, three rows of two below that. */
  .ed-stack__layers { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .ed-offer__grid {
    grid-template-columns: minmax(0, 660px) minmax(380px, 460px);
    justify-content: space-between;
  }
}

/* With no sample document the offer is one column at every width. After the
 * media queries on purpose: a media query adds no specificity, so this rule
 * wins them all by coming last. */
.ed-offer__grid--solo { grid-template-columns: minmax(0, 1fr); }

/* The hero photograph drifts down by 8% as the hero scrolls away (js/motion.js,
 * reduced motion excepted). It is 10% taller than the box, the extra BELOW
 * it, so at rest the photo's top edge is the hero's: nothing of it is hidden
 * under the bar (the owner, 27 September: "move hero image downward"). The
 * strip the drift uncovers at the top is 8.8% of the hero at the very end of
 * the exit, and at every scroll position it is less than the distance
 * scrolled, so it is always behind the sticky bar.
 *
 * ALWAYS, NOT ONLY ONCE THE SCRIPT HAS RUN. Tied to `ed-motion`, the photo
 * jumped 10% up and grew after it had been painted whenever the deferred
 * scripts arrived late — a layout shift on the largest image on the page
 * (review, 25 September 2026). Only the drift needs the script. */
.ed-hero--photo .ed-hero__media { inset-block-end: -10%; }

/* Reduced motion: layout.css already cuts every transition and animation to
 * nothing; the rail's own smooth scrolling goes with them (it is set on the
 * element, so the rule on <html> alone would not reach it). A card that
 * turns over swaps its faces at once: layout.css shortens durations but not
 * delays, so the back's 0.3s hiding delay is cleared here too. */
@media (prefers-reduced-motion: reduce) {
  .ed-rail { scroll-behavior: auto; }
  .ed-flip__in,
  .ed-flip__back { transition: none; }
  .ed-glow__halo,
  .ed-glow__ring { animation: none !important; }
  .ed-practice { animation: none; }
}
