/* EDN interactive graphics — scoped stylesheet for the Elementor build.
   Extracted from the EDN.run design system (template/assets/css/edn.css).
   Covers ONLY the three bespoke graphics that have no native Elementor widget:
   the hero constellation, the EDN garden, and the ADM workstreams, plus the
   plus the explanatory scenes inside the native Tabs widget.
   All page layout, typography and colour elsewhere is handled by Elementor
   Global Styles and container/widget controls — do not add page CSS here. */

/* --- tokens --------------------------------------------------------- */
:root {
  color-scheme: dark;
  /* Brand */
  --edn: #dfbd75;            /* gold: EDN, the whole product */
  --eva: #88dda6;            /* green: EVA and every primary action */
  --adm: #91bff3;            /* blue: ADMs */
  --primary: var(--eva);
  --on-primary: #101713;
  --warn: #e5b55e;
  --danger: #f16c67;
  --danger-text: #ffaaa1;
  /* Canvas and ink */
  --background: #111512;
  --canvas-deep: #0d100e;
  --card: #171d19;
  --popover: #1b231e;
  --accent: #263a2e;
  --border: #35473b;
  --hairline: #2c382f;
  --foreground: #f0f2ed;
  --body: #b5c0b7;
  --muted: #a4b0a6;
  /* Section accent (green by default, overridden per section) */
  --section-accent: var(--eva);
  --section-wash: #16261c;
  --section-border: #355440;
  /* Type */
  --font-display: 'Bebas Neue', Impact, 'Arial Narrow', sans-serif;
  --font-body: 'Source Code Pro', ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Motion */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* Layout */
  --page-gutter: clamp(16px, 5vw, 80px);
  --page-max: 1400px;
  --page-inline: max(var(--page-gutter), calc((100vw - var(--page-max)) / 2));
  --radius-input: 4px;
}
.adm { --section-accent: var(--adm); --section-wash: #17212e; --section-border: #354d69; }
.edn { --section-accent: var(--edn); --section-wash: #242016; --section-border: #5b4d31; }


/* --- graphic-scope resets and shared utilities ---------------------- */
.edn-graphic, .edn-graphic *, .edn-graphic *::before, .edn-graphic *::after { box-sizing: border-box; }
.edn-graphic fieldset { margin: 0; padding: 0; border: 0; min-inline-size: 0; }
.edn-graphic button { font: inherit; color: inherit; cursor: pointer; }
.edn-graphic h1, .edn-graphic h2, .edn-graphic h3, .edn-graphic p { margin: 0; }
.edn-graphic img, .edn-graphic svg, .edn-graphic canvas { display: block; max-width: 100%; }
.sr-only { position: absolute; width: 1px; height: 1px; max-width: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* Hello Elementor's reset gives <legend> display:table, and a table box treats width
   as a minimum -- the hidden legend then renders at full text width and scrolls the
   page sideways on small screens. Force a block box so width/overflow apply. */
.edn-graphic legend.sr-only { display: block; }
.gold-text { color: var(--edn); }
.muted { color: var(--muted); }
.edn-graphic .button {
  position: relative; overflow: hidden; display: inline-flex; align-items: center; justify-content: space-between; gap: 32px;
  padding: 16px 24px; min-height: 56px; border: 1px solid var(--primary); background: var(--primary); color: var(--on-primary);
  font-family: var(--font-body); font-size: 14px; font-weight: 600; cursor: pointer; transition: background 120ms, transform 220ms;
}
.edn-graphic .button > span[aria-hidden] { font-size: 24px; line-height: 1; }
.edn-graphic .button:hover { background: #a3edbd; transform: translateY(-2px); }
.edn-graphic .outline-button {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 16px; min-height: 48px;
  background: #142231; border: 1px solid var(--adm); color: var(--adm); font-family: var(--font-body); font-size: 14px; cursor: pointer;
}
.edn-graphic .outline-button:hover { background: #243a50; }
.edn-graphic .outline-button:disabled { opacity: .55; cursor: default; }
.motion-toggle:hover { color: var(--eva); }
.edn-graphic :focus-visible { outline: 2px solid var(--primary); outline-offset: 4px; }

/* --- hero headline lockup -------------------------------------------- */
/* The logo sits left of a strictly two-line headline, and both scale together
   against the copy column's width. Ported from the source design: Elementor has
   no control for container-query-fluid type, so this is a documented exception
   to "layout lives in Elementor". The px font-size is the fallback for engines
   without container queries -- keep it before the clamp. */
#edn-hero-copy { container-type: inline-size; min-width: 0; }
#edn-hero-title {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 16px;
  font-family: "Bebas Neue", Impact, "Arial Narrow", sans-serif; line-height: 1;
  font-size: 40px;
  font-size: clamp(2rem, calc((100cqw - 16px) / 7), 6rem);
}
#edn-hero-title > .elementor-widget-image { flex: 0 0 auto; width: auto; }
/* height:2em is exactly the two headline lines, so the mark matches the block. */
#edn-hero-title img { width: auto; height: 2em; max-width: none; }
#edn-hero-title > .elementor-widget-heading { min-width: 0; flex: 0 1 auto; }
#edn-hero-title .elementor-heading-title {
  font-size: 1em; line-height: 1; letter-spacing: 0; text-wrap: initial;
}

/* Same lockup treatment for the "In use today" headline: mark on the left, at the
   exact height of the two headline lines. */
#edn-proof-copy { container-type: inline-size; min-width: 0; }
#edn-proof-title {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 16px;
  font-family: "Bebas Neue", Impact, "Arial Narrow", sans-serif; line-height: 1;
  font-size: 36px;
  font-size: clamp(1.75rem, calc((100cqw - 16px) / 9), 4rem);
}
#edn-proof-title > .elementor-widget-image { flex: 0 0 auto; width: auto; }
#edn-proof-title img { width: auto; height: 2em; max-width: none; }
#edn-proof-title > .elementor-widget-heading { min-width: 0; flex: 0 1 auto; }
#edn-proof-title .elementor-heading-title {
  font-size: 1em; line-height: 1; letter-spacing: 0; text-wrap: initial;
}

/* --- hero constellation --------------------------------------------- */
/* `isolation` keeps the canvas's z-index:-1 inside the hero: it paints above the
   hero background but below the hero content, exactly as in the source design. */
#edn-hero { position: relative; isolation: isolate; }
/* The canvas lives in an Elementor HTML widget, whose wrapper is the positioning
   context and has no height of its own. Stretch the wrapper over the hero so the
   absolutely positioned canvas inside it has something to fill. */
#edn-constellation { position: absolute; inset: 0; pointer-events: none; }
#edn-constellation > .elementor-widget-container { height: 100%; }
.hero-constellation { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.hero-constellation canvas { width: 100%; height: 100%; }

/* --- EDN garden ------------------------------------------------------ */
.garden { position: relative; min-width: 0; padding: 16px; background: transparent; --section-accent: var(--eva); --adm-diameter: 48px; }
.garden-label { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; color: var(--edn); font-family: var(--font-display); font-size: 28px; line-height: 1; letter-spacing: 1px; }
.garden-product { font-family: var(--font-body); font-size: 12px; letter-spacing: .4px; text-transform: uppercase; }
.garden-corner { font-family: var(--font-body); font-size: 24px; }
.garden-space { position: relative; width: 100%; aspect-ratio: 1; margin: 16px 0 8px; isolation: isolate; }
.garden-boundary { position: absolute; inset: 2%; border: 1px solid #dfbd7545; border-radius: 50%; background: radial-gradient(circle, #88dda607 0 55%, transparent 56%); }
.garden-boundary::before { content: ''; position: absolute; inset: 7%; border-radius: 50%; border: 1px dashed #dfbd751c; }
.garden-orbit { position: absolute; inset: 26%; border: 1px solid #88dda61f; border-radius: 50%; animation: garden-breathe 6s ease-in-out infinite; }
.garden-connections { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.garden-link { fill: none; stroke: #91bff35c; stroke-width: 1.2; stroke-dasharray: 1; animation: connection-grow 800ms var(--ease-out) both; }
.garden-eva, .garden-adm {
  position: absolute; display: flex; flex-direction: column; align-items: center; justify-content: center; transform: translate(-50%, -50%);
  border-radius: 50%; cursor: pointer; padding: 0; z-index: 2; background: #132a1d; color: var(--eva);
  transition: box-shadow 220ms, border-color 220ms, background 220ms;
}
.garden-eva { top: 50%; left: 50%; width: 76px; height: 76px; --eva-drop: 8px; border: 1px solid var(--eva); box-shadow: 0 0 32px #88dda612; }
.garden-eva::before { content: ''; position: absolute; inset: -7px; border: 1px solid #88dda62b; border-radius: 50%; animation: garden-breathe 4s ease-in-out infinite; pointer-events: none; }
.garden-eva > span { font-family: var(--font-display); font-size: 30px; line-height: 1; transform: translateY(calc(3px + var(--eva-drop, 0px))); }
.garden-eva small { margin-top: 0; font-size: 12px; transform: translateY(calc(-1px + var(--eva-drop, 0px))); }
.garden-eva[aria-pressed=true], .garden-eva:hover { border-color: #c0fbd5; box-shadow: 0 0 32px #88dda636; }
.eva-birth { position: absolute; inset: 0; border: 1px solid var(--eva); border-radius: 50%; pointer-events: none; animation: birth-ripple 900ms ease-out both; }
.garden-adm {
  left: var(--node-x); top: var(--node-y); width: var(--adm-diameter); height: var(--adm-diameter);
  color: var(--node-ink, var(--adm)); border: 1px solid color-mix(in srgb, var(--node-ink, var(--adm)) 70%, transparent);
  background: color-mix(in srgb, var(--node-ink, var(--adm)) 13%, #101820);
  animation: node-bloom 650ms var(--ease-out) both;
  transition: color 100ms linear, border-color 100ms linear, background 100ms linear, box-shadow 220ms;
}
.garden-adm > span { font-size: 14px; font-weight: 600; line-height: 1.3; }
.garden-adm small { font-size: 9px; line-height: 1.15; opacity: .85; max-width: 94%;
  overflow-wrap: anywhere; text-align: center; }
.garden-adm[aria-pressed=true], .garden-adm:hover { border-color: #d3e8ff; box-shadow: 0 0 24px #91bff344; }
.garden-adm[data-health=warning] { animation: node-distress 1.3s ease-in-out infinite; }
.garden-adm[data-health]:not([data-health=steady]):not([data-health=restored]) { border-color: var(--node-ink); box-shadow: 0 0 22px color-mix(in srgb, var(--node-ink) 25%, transparent); }
.recovery-helper {
  position: absolute; z-index: 4; width: calc(var(--adm-diameter) * 1.65); height: calc(var(--adm-diameter) * 1.65);
  border: 2px solid var(--eva); border-radius: 50%; background: #88dda60c; box-shadow: inset 0 0 18px #88dda62b, 0 0 24px #88dda625; pointer-events: none;
  transition: left 90ms linear, top 90ms linear, opacity 90ms linear, transform 90ms linear;
}
.recovery-helper i { position: absolute; inset: 6px; border: 1px solid #88dda668; border-radius: 50%; }
.recovery-helper span { position: absolute; inset: -6px; border: 1px dashed #88dda666; border-radius: 50%; }
.recovery-helper[data-phase=healing] span { animation: support-pulse 1.4s ease-in-out infinite; }
.garden-seed-note { position: absolute; left: 10%; right: 10%; top: 78%; color: var(--muted); text-align: center; font-size: 12px; }
/* The count sits inside a gold frame -- what EDN contains -- with the product
   name outside it, so the rules above and below are no longer needed. */
.garden-readout {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  padding: 14px 0; font-size: 12px;
}
.garden-readout > .garden-inside {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
  padding: 8px 12px; border: 1px solid var(--edn);
}
.garden-readout > .gold-text {
  font-family: var(--font-display); font-size: 15px; letter-spacing: .05em;
}
.garden-readout > .scene-rerun { margin-left: auto; }
.garden-readout > span { display: inline-flex; align-items: center; gap: 8px; }
.legend-dot { display: inline-block; width: 5px; height: 5px; border-radius: 50%; }
.legend-dot.green { background: var(--eva); }
.legend-dot.blue { background: var(--adm); }
.garden-health { display: flex; align-items: center; gap: 8px; min-height: 48px; margin-top: 8px; font-size: 12px; line-height: 1.65; color: var(--muted); }
.garden-health > i { display: block; width: 5px; height: 5px; border-radius: 50%; background: var(--eva); flex-shrink: 0; }
.garden-health[data-phase=warning] { color: var(--warn); }
.garden-health[data-phase=warning] > i { background: var(--warn); }
.garden-health[data-phase=stuck] { color: #f59a96; }
.garden-health[data-phase=stuck] > i { background: var(--danger); }
.garden-health[data-phase=healing], .garden-health[data-phase=returning], .garden-health[data-phase=restored] { color: var(--eva); }
.garden-description { min-height: 104px; padding-top: 8px; }
/* Spells out the three acronyms once, quietly, above the readout title. */
.garden-key {
  display: block; margin-bottom: 8px; min-height: 1.6em; font-size: 10px;
  line-height: 1.6; letter-spacing: .06em; text-transform: uppercase; color: #6d7a71;
  opacity: 1; transition: opacity 200ms ease;
}
.garden-key[data-swap='out'] { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .garden-key { transition: none !important; opacity: 1 !important; }
}
.garden-description strong { display: block; font-family: var(--font-display); font-size: 24px; font-weight: 400; text-transform: uppercase; line-height: 1.12; color: var(--foreground); }
.garden-description p { font-size: 14px; line-height: 1.75; margin-top: 8px; }
.garden-controls { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 16px; align-items: center; }
/* A class-level display:flex outranks the UA [hidden] rule, so state it here. */
.garden-controls[hidden] { display: none; }
.garden-controls .button { flex: 1 1 160px; padding: 12px 16px; min-height: 48px; }
.diagram-note { font-size: 12px; color: var(--muted); line-height: 1.65; margin-top: 16px; }
.garden-explore { display: flex; justify-content: space-between; align-items: center; min-height: 48px; color: var(--eva); font-size: 14px; margin-top: 8px; }


/* Nested Tabs grows its titles with flex-grow:1, so they stretch from their own
   text widths and end up uneven. The design wants three equal columns, and there
   is no native control for flex-basis -- hence this one rule. */
#edn-eva-tabs .e-n-tabs-heading > .e-n-tab-title { flex: 1 1 0; min-width: 0; }

/* --- ADM workstreams ------------------------------------------------- */
.workstreams { background: radial-gradient(ellipse at 50% 50%, #1a2a3b, #111820 70%); padding: 16px; }
.workstreams-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; font-size: 12px; }
.workstreams-eva { display: flex; flex-direction: column; align-items: center; justify-content: center; border: 1px solid var(--eva); background: #163322; width: 152px; min-height: 88px; margin: 32px auto 0; padding: 16px; }
.workstreams-eva > span { font-family: var(--font-display); font-size: 32px; color: var(--eva); line-height: 1; }
.workstreams-eva small { font-size: 12px; color: var(--body); margin-top: 8px; }
.workstreams-branches { position: relative; height: 64px; }
.workstreams-branches::before { content: ''; position: absolute; left: 50%; top: 0; height: 24px; border-left: 1px solid #91bff366; }
.workstreams-branches::after { content: ''; position: absolute; left: 16.667%; right: 16.667%; top: 24px; border-top: 1px solid #91bff366; }
.workstreams-branches i { position: absolute; top: 24px; bottom: 0; border-left: 1px solid #91bff366; }
.workstreams-branches i:nth-child(1) { left: 16.667%; }
.workstreams-branches i:nth-child(2) { left: 50%; }
.workstreams-branches i:nth-child(3) { left: 83.333%; }
.workstream-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.workstream { padding: 16px 8px; border: 1px solid #91bff344; background: #142231; min-width: 0; text-align: center; transition: border-color 460ms; }
.workstream[data-stage='3'] { border-color: var(--adm); }
.workstream-node { font-family: var(--font-display); font-size: 24px; color: var(--adm); line-height: 1.2; }
.workstream-node > span { display: block; font-family: var(--font-body); font-size: 12px; }
.workstream-label { display: block; font-size: 12px; color: var(--muted); margin-top: 16px; }
.workstream-meter { height: 3px; background: #91bff326; margin: 16px 0; overflow: hidden; }
.workstream-meter i { display: block; height: 100%; width: 100%; background: var(--adm); transform-origin: left; transform: scaleX(0); transition: transform 700ms var(--ease-out); }
.workstream > strong { display: block; font-size: 12px; font-weight: 400; color: var(--body); overflow-wrap: anywhere; }
.workstream[data-stage='3'] > strong { color: var(--adm); }
.workstream-dots { display: flex; justify-content: center; gap: 4px; margin-top: 16px; }
.workstream-dots i { width: 5px; height: 5px; border: 1px solid #91bff34d; border-radius: 50%; }
.workstream-dots i.lit { background: var(--adm); border-color: var(--adm); }
.workstreams-footer { display: flex; flex-direction: column; gap: 24px; margin-top: 32px; }
.workstreams-footer strong { display: block; font-family: var(--font-display); font-size: 26px; text-transform: uppercase; font-weight: 400; line-height: 1.2; }
.workstreams-footer p { font-size: 14px; margin-top: 8px; }

/* --- motion ---------------------------------------------------------- */
@keyframes enter { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes node-bloom { from { left: 50%; top: 50%; opacity: 0; transform: translate(-50%, -50%) scale(.25); } to { left: var(--node-x); top: var(--node-y); opacity: 1; transform: translate(-50%, -50%) scale(1); } }
@keyframes birth-ripple { from { transform: scale(1); opacity: .55; } to { transform: scale(2.3); opacity: 0; } }
@keyframes connection-grow { from { stroke-dashoffset: 1; opacity: 0; } to { stroke-dashoffset: 0; opacity: 1; } }
@keyframes garden-breathe { 0%, 100% { transform: scale(1); opacity: .65; } 50% { transform: scale(1.08); opacity: 1; } }
@keyframes line-current { to { stroke-dashoffset: -48; } }
@keyframes proof-flow { 0%, 100% { transform: translateX(-105%); opacity: 0; } 20%, 75% { opacity: .6; } 90% { transform: translateX(310%); opacity: 0; } }
@keyframes node-distress { 0%, 100% { transform: translate(-50%, -50%) rotate(0deg); } 35% { transform: translate(calc(-50% + 1px), -50%) rotate(2deg); } 65% { transform: translate(calc(-50% - 1px), -50%) rotate(-2deg); } }
@keyframes support-pulse { 0%, 100% { transform: scale(1); opacity: .45; } 50% { transform: scale(1.08); opacity: 1; } }
/* Scroll reveal: content is visible by default; JS adds .observe, then .visible when in view. */
.observe { opacity: 0; transform: translateY(24px); transition: opacity 460ms var(--ease-out), transform 460ms var(--ease-out); }
.observe.visible { opacity: 1; transform: none; }
/* Pausing stops only looping decoration. One-shot entrances always finish, so a page opened
   in a background tab (document.hidden) never freezes with invisible content. */
[data-motion=paused] .garden-orbit, [data-motion=paused] .garden-eva::before, [data-motion=paused] .recovery-helper span,
[data-motion=paused] .garden-adm[data-health=warning], [data-motion=paused] .proof-trace::after,
.garden[data-active=false] .garden-orbit, .garden[data-active=false] .garden-eva::before, .garden[data-active=false] .recovery-helper span { animation-play-state: paused !important; }
[data-motion=paused] .observe { opacity: 1; transform: none; }
[data-motion=paused] .garden-link, .garden[data-active=false] .garden-link { animation: none; stroke-dashoffset: 0; opacity: 1; }
[data-motion=paused] .garden-adm, .garden[data-active=false] .garden-adm { animation: none; }
[data-motion=paused] .eva-birth, .garden[data-active=false] .eva-birth { display: none; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .observe { opacity: 1; transform: none; }
  .garden-adm { transform: translate(-50%, -50%); }
  .garden-link { stroke-dashoffset: 0; opacity: 1; }
}


/* --- breakpoints ------------------------------------------------------ */
@media (min-width: 25rem) {
  .garden { --adm-diameter: 56px; }
  .garden-eva { width: 88px; height: 88px; }
  .garden-eva > span { font-size: 36px; }
  .garden-description { min-height: 112px; }
  .workstream > strong { font-size: 14px; }
}
@media (min-width: 48rem) {
  .garden { padding: 24px; }
  .workstreams { padding: 32px; }
  .workstream-grid { gap: 24px; }
  .workstream { padding: 32px 24px; }
  .workstream-node { font-size: 32px; }
  .workstream-node > span { display: inline; font-size: 14px; margin-left: 8px; }
  .workstream-label { font-size: 14px; }
  .workstream > strong { font-size: 16px; }
  .workstream-meter { margin-block: 24px; }
  .workstreams-footer { flex-direction: row; align-items: center; justify-content: space-between; }
  .outline-button { flex-shrink: 0; }
}
/* Story garden: replaces the `.garden-story-layout .garden` rules, which in the
   original depended on a CSS grid that an Elementor container now provides. */
.edn-garden-story .garden { width: 100%; max-width: 560px; margin-inline: auto; }
@media (min-width: 64rem) {
  .garden-compact { padding: 16px 24px; --adm-diameter: 48px; }
  .garden-compact .garden-space { margin-block: 8px; }
  .garden-compact .garden-eva { width: 80px; height: 80px; }
  .garden-compact .garden-description { min-height: 112px; }
  .edn-garden-story .garden { max-width: none; margin-inline: 0; --adm-diameter: 64px; }
  .edn-garden-story .garden-space { max-width: 560px; margin-inline: auto; }
  .edn-garden-story .garden-eva { width: 104px; height: 104px; }
}

/* Phone: let the graphic go full-bleed (3px either side) so the outer ring uses the
   whole width, and grow the nodes to match so a label like "Developer" or
   "Architect" fits inside the circle. The garden sits inside padded ancestors, so
   it breaks out with the standard 50%/50vw trick; the text rows below get their
   own inset back. */
@media (max-width: 767px) {
  .edn-garden-story .garden {
    width: auto; max-width: none;
    margin-inline: -13px;
    padding-inline: 0;
    --adm-diameter: 64px;
  }
  .edn-garden-story .garden > .garden-readout,
  .edn-garden-story .garden > .garden-health,
  .edn-garden-story .garden > .garden-description,
  .edn-garden-story .garden > .diagram-note { padding-inline: 13px; }
  .edn-garden-story .garden-eva { width: 92px; height: 92px; }
  .edn-garden-story .garden-eva > span { font-size: 34px; }
}

/* Project marks sit beside their name on one line at every width. */
#edn-mark-warleague, #edn-mark-hanstudios { flex-wrap: nowrap; align-items: center; }
#edn-mark-warleague > .elementor-widget-image,
#edn-mark-hanstudios > .elementor-widget-image { flex: 0 0 auto; width: auto; }
#edn-mark-warleague > .elementor-widget-heading,
#edn-mark-hanstudios > .elementor-widget-heading { min-width: 0; flex: 0 1 auto; }

/* The two hero calls to action share a width: a two-track grid sizes both to the
   same column instead of letting each shrink to its own label. */
#edn-hero-cta {
  display: grid; grid-template-columns: 1fr; gap: 24px;
  max-width: 248px; align-items: stretch;
}
#edn-hero-cta > .elementor-widget-button { width: auto; min-width: 0; }
#edn-hero-cta .elementor-button { width: 100%; justify-content: space-between; }
@media (max-width: 767px) {
  #edn-hero-cta { gap: 16px; max-width: none; }
}

/* Elementor form fields sit on their default white, where the palette's body
   colour (#B5C0B7) gives ~1.9:1 -- barely legible. Elementor has no placeholder
   colour control, so set one here; the field text itself is set on the widget. */
#edn-beta-form input::placeholder,
#edn-beta-form textarea::placeholder { color: #5F6B62; opacity: 1; }
#edn-beta-form select:invalid, #edn-beta-form select .placeholder { color: #5F6B62; }

/* Phone: the submit matches the field width. Elementor's button_width sets the
   field-group column, but the button inside still sizes to its label. */
@media (max-width: 767px) {
  #edn-beta-form .elementor-field-type-submit { width: 100%; }
  #edn-beta-form .elementor-field-type-submit .elementor-button {
    width: 100%; justify-content: space-between;
  }
}

/* ==========================================================================
   Explanatory scenes. Each EVA tab gets its own composition; the shared bits
   are the label, the tag vocabulary and the "why" line. Status is always
   carried by a word as well as a colour, so it survives a mono display.
   ========================================================================== */
.scene { display: block; }
/* The label carries the running caption, so it reads as content rather than a
   footnote and cross-fades instead of snapping between phases. A reserved
   height keeps the graphic below it from jumping when the wording changes. */
/* Scoped to the graphic so it outranks the theme's paragraph reset, which was
   flattening the gap between the caption and the frame below it. */
/* The caption and its one control share a row; the row carries the spacing so
   the caption can cross-fade without moving anything. */
.edn-graphic .scene-head {
  display: flex; align-items: center; gap: 12px; margin: 0 0 18px;
}
.edn-graphic .scene-label {
  flex: 1 1 auto; min-width: 0;
  font-size: 13px; line-height: 1.5; color: var(--body);
  border-left: 2px solid #dfbd7566; padding-left: 10px; margin: 0;
  min-height: 1.5em; opacity: 1; transition: opacity 200ms ease;
}
/* One glyph, nothing else: it re-runs this graphic's sequence. */
.edn-graphic .scene-rerun {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: transparent; border: 1px solid var(--hairline);
  color: var(--muted); font-size: 15px; line-height: 1; cursor: pointer;
  transition: color 200ms, border-color 200ms;
}
.edn-graphic .scene-rerun:hover { color: var(--eva); border-color: var(--eva); }
.edn-graphic .scene-rerun:focus-visible { outline: 2px solid var(--eva); outline-offset: 2px; }
.edn-graphic .scene-label[data-swap='out'] { opacity: 0; }
@media (max-width: 47.99rem) { .edn-graphic .scene-label { min-height: 3em; } }
@media (prefers-reduced-motion: reduce) {
  .edn-graphic .scene-label { transition: none !important; opacity: 1 !important; }
}
.scene-why { font-size: 14px; line-height: 1.75; color: var(--body); margin-top: 20px; max-width: 62ch; }
.scene-why strong { color: var(--foreground); }

.tag {
  display: inline-block; flex-shrink: 0; padding: 3px 8px; border: 1px solid;
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
}
.tag-now   { color: #0f1a13; background: var(--eva); border-color: var(--eva); font-weight: 600; }
.tag-plain { color: var(--adm); border-color: #91bff359; }
.tag-quiet { color: var(--muted); border-color: var(--hairline); }
.tag-rec   { color: var(--eva); border-color: var(--eva); }
.tag-human { color: var(--edn); border-color: var(--edn); font-weight: 600; }

/* --- Focus: a ranked queue, top item lifted --------------------------- */
.queue { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.queue-row {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 16px; border: 1px solid var(--hairline); background: #121814;
}
.queue-row.is-top {
  border-color: var(--eva); background: #16241c;
  box-shadow: inset 3px 0 0 var(--eva);
}
.queue-rank { font-family: var(--font-display); font-size: 22px; color: var(--muted); line-height: 1; }
.queue-row.is-top .queue-rank { color: var(--eva); }
.queue-task { flex: 1 1 auto; min-width: 0; display: block; }
@media (max-width: 30rem) {
  .queue-open { gap: 8px 12px; }
  .queue-open .queue-task { flex-basis: calc(100% - 44px); }
  .queue-why { padding-left: 16px; }
}
.queue-task strong { display: block; font-size: 15px; color: var(--foreground); line-height: 1.35; }
.queue-task small { display: block; font-size: 12px; color: var(--muted); margin-top: 3px; }

/* --- Blockers: a dependency path with one broken link ----------------- */
.path { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 0; }
.path-step { position: relative; padding: 0 0 22px 30px; }
.path-step::before {
  content: ''; position: absolute; left: 7px; top: 18px; bottom: 0; border-left: 2px solid var(--hairline);
}
.path-step:last-child { padding-bottom: 0; }
.path-step:last-child::before { display: none; }
.path-step.is-blocked::before { border-left-style: dashed; border-left-color: var(--danger); }
.path-mark {
  position: absolute; left: 0; top: 4px; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--hairline); background: var(--canvas-deep);
}
.path-step.is-done .path-mark { border-color: var(--eva); background: var(--eva); }
/* Blocked also changes shape, not only colour. */
.path-step.is-blocked .path-mark { border-color: var(--danger); border-radius: 0; transform: rotate(45deg); }
.path-step.is-waiting .path-mark { border-style: dashed; border-color: var(--warn); }
.path-step strong { display: block; font-size: 15px; color: var(--foreground); line-height: 1.3; }
.path-step small { display: block; font-size: 12px; margin-top: 3px; color: var(--muted); }
.path-step.is-blocked small { color: var(--danger-text); }
.path-step.is-waiting small { color: var(--warn); }
.lane-continues { list-style: none; margin: 20px 0 0; padding: 16px 0 0; border-top: 1px solid var(--hairline);
  display: grid; gap: 8px; font-size: 13px; color: var(--body); }
.lane-continues li { display: flex; align-items: center; gap: 12px; }

/* --- Decisions: a brief, two options, an explicit human boundary ------ */
.brief-q { font-family: var(--font-display); font-size: 26px; line-height: 1.15; text-transform: uppercase;
  color: var(--foreground); margin-bottom: 20px; }
.options { display: grid; gap: 12px; }
.option { position: relative; padding: 18px 18px 16px; border: 1px solid var(--hairline); background: #121814; }
.option.is-rec { border-color: var(--eva); background: #15211a; }
.option-key { display: block; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 6px; }
.option strong { display: block; font-size: 16px; color: var(--foreground); line-height: 1.35; }
.option ul { margin: 10px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.7; color: var(--body); }
.option .tag-rec { margin-top: 12px; }
.approval {
  display: flex; align-items: flex-start; gap: 14px; margin-top: 16px;
  padding: 16px; border: 1px solid #dfbd754d; background: #1d1a12;
}
.approval p { font-size: 13px; line-height: 1.7; color: var(--body); }

/* --- Wider screens: give each scene its natural composition ----------- */
@media (min-width: 48rem) {
  .queue-row { padding: 16px 20px; gap: 20px; }
  .queue-task strong { font-size: 16px; }
  .brief-q { font-size: 32px; }
  .options { grid-template-columns: 1fr 1fr; gap: 20px; }
  .compare-grid { grid-template-columns: 1fr 1fr; gap: 24px; }
  .compare-side { padding: 24px; }
  /* The dependency path runs left to right where there is room. */
  .path { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
  .path-step { padding: 34px 16px 0 0; }
  .path-step::before { left: 18px; right: 0; top: 7px; bottom: auto;
    border-left: 0; border-top: 2px solid var(--hairline); }
  .path-step.is-blocked::before { border-top-style: dashed; border-top-color: var(--danger); border-left: 0; }
  .path-mark { top: 0; }
  .lane-continues { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   Focus and form legibility. The theme leaves the UA focus ring at its default
   black, which is invisible on this canvas -- every interactive element on the
   page needs a visible ring, not just the ones inside .edn-graphic.
   ========================================================================== */
#edn-eva-tabs .e-n-tab-title:focus-visible,
.elementor-button:focus-visible,
.elementor-field:focus-visible,
.elementor-field-group select:focus-visible,
.elementor a:focus-visible,
.elementor button:focus-visible {
  outline: 2px solid var(--eva);
  outline-offset: 3px;
}
/* Fields sit on white, so their focus ring needs the darker ink to stay visible. */
#edn-beta-form .elementor-field:focus-visible,
#edn-beta-form select:focus-visible {
  outline: 2px solid #1d3b28; outline-offset: 2px;
}
#edn-beta-form .elementor-field:focus { border-color: #1d3b28; }

/* Validation and status messages: readable, and never colour alone. */
.elementor-message { font-size: 13px; line-height: 1.6; padding: 10px 12px; border: 1px solid; }
.elementor-message.elementor-message-danger,
#edn-beta-form .elementor-message-danger {
  color: #7a1d19; background: #ffe9e7; border-color: #b3352e;
}
.elementor-message.elementor-message-success,
#edn-beta-form .elementor-message-success {
  color: #10331f; background: #dff6e7; border-color: #2f7d4f;
}
#edn-beta-form .elementor-field-group > label { color: var(--foreground); }

/* ==========================================================================
   Horizontal rhythm. Boxed containers ran the full 1400px, so paragraphs
   stretched to ~160 characters and sections read as mostly empty space.
   Cap the measure and let the panels sit against a consistent grid.
   ========================================================================== */
/* The body text runs to the width of the heading above it -- in the hero, the
   width of the logo-and-headline lockup. The columns already set a sensible
   measure, so a second cap on top of them only made these blocks look narrow
   for no reason. */
.elementor-widget-text-editor p { max-width: none; }
#in-use .elementor-widget-text-editor p { max-width: 44ch; }
/* "How it works" runs its intro the full width of the section: it is two
   paragraphs of argument, not a one-line subtitle like the other sections. */
#how .elementor-widget-text-editor p { max-width: none; }
#beta .elementor-widget-text-editor p { max-width: none; }

/* The explanatory panels get a working width rather than the full container. */
/* Graphics fill the content column; only prose keeps a reading measure. */
.scene, .compare, .coord, .adm-scene { max-width: none; }
.illus-note { letter-spacing: .02em; }

@media (min-width: 64rem) {
  /* Headline blocks stay narrower than the panels beneath them. */
  #eva  > .e-con-inner > .e-con:first-child,
  #adm  > .e-con-inner > .e-con:first-child,
  #overview > .e-con-inner > .e-con:first-child { max-width: 760px; }
}

/* ==========================================================================
   Scene interaction states. Every control is a real button, so focus and
   pressed states come for free; the styles just make them legible.
   ========================================================================== */
.scene-lede { font-size: 14px; line-height: 1.7; color: var(--body); margin-bottom: 18px; max-width: 60ch; }
.scene-controls { margin-top: 18px; }

/* Focus queue rows open their reasoning. */
.queue-row { display: block; padding: 0; }
.queue-open {
  display: flex; align-items: center; gap: 12px; width: 100%; flex-wrap: wrap;
  padding: 14px 16px; background: none; border: 0; text-align: left; color: inherit;
}
/* Without min-width:0 the task column refuses to shrink below its longest line
   and the row pushes the page sideways on a phone. */
.queue-open .queue-task { min-width: 0; flex: 1 1 55%; }
.queue-open .queue-task strong,
.queue-open .queue-task small { overflow-wrap: anywhere; }
.queue-open:hover { background: #16201a; }
.queue-chev {
  width: 9px; height: 9px; flex-shrink: 0; border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted); transform: rotate(45deg); transition: transform 160ms;
}
.queue-open[aria-expanded='true'] .queue-chev { transform: rotate(-135deg); }
.queue-why {
  margin: 0; padding: 0 16px 14px 52px; font-size: 13px; line-height: 1.7; color: var(--body);
}
.queue-why[hidden] { display: none; }

/* Blockers: a fourth state for a path that has resumed. */
.path-step.is-moving .path-mark { border-color: var(--eva); border-style: solid; }
.path-step.is-moving small { color: var(--eva); }
.path-step.is-moving::before { border-color: var(--eva); border-style: solid; }
[data-blockers-toggle][aria-pressed='true'] { border-color: var(--eva); color: var(--eva); }

/* Decisions: options are buttons and report the choice. */
.option {
  display: block; width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer;
}
.option:hover { border-color: #88dda67a; }
.option[aria-pressed='true'] {
  border-color: var(--eva); background: #17281e; box-shadow: inset 3px 0 0 var(--eva);
}
.option[aria-pressed='true'] .option-key { color: var(--eva); }

/* Compare: task buttons pair across the two sides. */
.scatter li, .ordered li { padding: 0; }
.scatter button, .ordered button {
  display: block; width: 100%; padding: 10px 12px; background: none; border: 0;
  text-align: left; font: inherit; color: inherit; cursor: pointer;
}
.scatter button:hover, .ordered button:hover { background: #16201a; }
.scatter li:has(button[aria-pressed='true']),
.ordered li:has(button[aria-pressed='true']) {
  border-color: var(--eva); background: #16241c; box-shadow: inset 3px 0 0 var(--eva);
}

/* Grid and flex children default to min-width:auto, so a long task title stops
   the whole scene from shrinking and the page scrolls sideways on a phone.
   Every box in a scene is allowed to be narrower than its content. */
.scene, .compare, .workstreams,
.queue, .queue-row, .queue-open, .queue-why,
.path, .path-step,
.options, .option,
.compare-grid, .compare-side,
.scatter, .scatter li, .scatter button,
.ordered, .ordered li, .ordered button,
.lane-continues, .lane-continues li,
.workstream-grid, .workstream { min-width: 0; }
.scene *, .compare * { max-width: 100%; }
.queue-why { padding-left: 16px; padding-right: 16px; }
@media (min-width: 30rem) { .queue-why { padding-left: 52px; } }

/* The queue row is an explicit grid on small screens: rank, then the task on its
   own track where it can wrap, with the tag beneath it. Flex was letting the
   title set the row's minimum width and push the page sideways. */
.queue-open .queue-task,
.queue-open .queue-task strong,
.queue-open .queue-task small {
  white-space: normal; overflow-wrap: break-word; word-break: break-word;
}
@media (max-width: 40rem) {
  .queue-open {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: start; gap: 6px 12px;
  }
  .queue-open .queue-rank { grid-column: 1; grid-row: 1; }
  .queue-open .queue-task { grid-column: 2; grid-row: 1; flex: none; }
  .queue-open .queue-chev  { grid-column: 3; grid-row: 1; margin-top: 6px; }
  .queue-open .tag         { grid-column: 2; grid-row: 2; justify-self: start; }
}

/* Three narrow columns on a phone: let the ADM labels wrap rather than clip. */
.workstream-label, .workstream-output, .workstream-node,
.workstream > strong { overflow-wrap: anywhere; hyphens: auto; }
@media (max-width: 26rem) {
  .workstream-label, .workstream-output { font-size: 11px; }
}

/* Decisions scene on a phone: the display-face question and the option lists
   both needed permission to wrap inside their own boxes. */
.brief-q, .option strong, .option li, .approval p, .scene-lede {
  overflow-wrap: break-word; word-break: break-word;
}
.option ul { padding-left: 16px; margin-right: 0; }
.option, .approval { box-sizing: border-box; }
.approval { flex-wrap: wrap; }
@media (max-width: 30rem) {
  .brief-q { font-size: 22px; }
  .option { padding: 14px; }
  .approval { padding: 14px; gap: 10px; }
}

/* Explicit single-column track on phones: a grid item's automatic minimum is its
   content, which was letting the option cards set the scene's width. */
.options { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 48rem) { .options { grid-template-columns: minmax(0,1fr) minmax(0,1fr); } }
.scene, .compare { overflow-x: clip; }

/* ==========================================================================
   Coordination stage. One scene: scattered work becomes organised work, with
   the same tiles moving rather than a second list appearing. Positions live in
   CSS per arrangement; the runtime only flips booleans on the wrapper.
   ========================================================================== */
.coord { max-width: none; }
.coord-stage {
  position: relative; width: 100%; aspect-ratio: 900 / 470;
  background: radial-gradient(ellipse at 50% 0%, #16241c66, transparent 70%);
  border: 1px solid var(--hairline); overflow: hidden;
}
.coord-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.coord-links path { fill: none; stroke: #91bff34d; stroke-width: 1.5; opacity: 0; transition: opacity 420ms; }
.coord-links path.is-dep { stroke: #dfbd7566; stroke-dasharray: 4 4; }
.coord[data-arranged='true'] .coord-links path { opacity: 1; }
.coord-links path.is-traced { stroke: var(--eva); stroke-width: 2.5; opacity: 1; }

/* Shared goal */
.coord-goal {
  position: absolute; left: 50%; top: 11%; transform: translate(-50%, -50%) scale(.9);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 18px; border: 1px solid var(--edn); background: #1d1a12;
  opacity: 0; transition: opacity 420ms, transform 420ms var(--ease-out);
}
.coord[data-goal='true'] .coord-goal { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.coord-goal span { font-family: var(--font-display); font-size: 20px; color: var(--edn); line-height: 1; }
.coord-goal small { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* Later zone */
.coord-zone {
  position: absolute; left: 8%; right: 8%; top: 64%; bottom: 12%;
  border: 1px dashed var(--hairline); opacity: 0; transition: opacity 420ms;
}
.coord-zone span {
  position: absolute; left: 10px; top: 8px; font-size: 10px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.coord[data-later='true'] .coord-zone { opacity: 1; }

/* Task tiles keep their identity while they travel. */
.tile {
  position: absolute; transform: translate(-50%, -50%) scale(var(--tile-scale, 1));
  display: grid; grid-template-columns: auto 1fr; grid-auto-rows: auto;
  gap: 1px 8px; align-items: center; width: 132px; padding: 9px 11px;
  background: #121a15; border: 1px solid var(--hairline); color: var(--foreground);
  text-align: left; cursor: pointer;
  transition: left 760ms var(--ease-out), top 760ms var(--ease-out),
              transform 620ms var(--ease-out), opacity 420ms, border-color 240ms,
              background 240ms, width 420ms;
}
.tile:hover { border-color: #88dda67a; }
.tile-icon { grid-row: 1 / span 2; color: var(--adm); display: flex; }
.tile-icon svg { width: 16px; height: 16px; }
.tile-name { font-size: 13px; font-weight: 600; line-height: 1.2; }
.tile-sub { font-size: 10px; color: var(--muted); line-height: 1.3; }
.tile-own {
  grid-column: 2; font-size: 9px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--adm); opacity: 0; max-height: 0; transition: opacity 320ms, max-height 320ms;
}
.coord[data-owned='true'] .tile-own { opacity: 1; max-height: 14px; }
.tile[data-kind='later'] { --tone: var(--muted); }
.coord[data-later='true'] .tile[data-kind='later'] { opacity: .62; width: 116px; }
.coord[data-later='true'] .tile[data-kind='later'] .tile-icon { color: var(--muted); }

/* The duplicate collapses into the real task. */
.tile[data-tile='api2'] { border-style: dashed; opacity: .75; }
.tile[data-tile='api2'] .tile-sub { color: var(--danger-text); }
/* Once merged, the duplicate is gone for good. Opacity alone was not enough:
   the traced-dimming rule below is (0,5,0) because :not() counts its argument,
   so it outranked this and faded the merged tile back in at 0.38 whenever a task
   was selected. visibility takes it out of play regardless of opacity, delayed so
   the merge still fades. */
.coord[data-deduped='true'] .tile[data-tile='api2'],
.coord[data-deduped='true'][data-traced] .tile[data-tile='api2'] {
  opacity: 0; --tile-scale: .6; pointer-events: none; visibility: hidden;
  transition: opacity 420ms, transform 620ms var(--ease-out), visibility 0s linear 420ms;
}

/* --- scattered arrangement (the default) --- */
.tile[data-tile='api']      { left: 15%; top: 22%; }
.tile[data-tile='api2']   { left: 33%; top: 44%; }
.tile[data-tile='tests']    { left: 68%; top: 17%; }
.tile[data-tile='docs']     { left: 80%; top: 55%; }
.tile[data-tile='settings'] { left: 20%; top: 72%; }
.tile[data-tile='onboard']  { left: 53%; top: 79%; }

/* --- organised arrangement --- */
.coord[data-arranged='true'] .tile[data-tile='api']    { left: 22%; top: 46%; }
.coord[data-arranged='true'] .tile[data-tile='api2'] { left: 22%; top: 46%; }
.coord[data-arranged='true'] .tile[data-tile='tests']  { left: 50%; top: 46%; }
.coord[data-arranged='true'] .tile[data-tile='docs']   { left: 78%; top: 46%; }
.coord[data-arranged='true'] .tile[data-tile='settings'] { left: 30%; top: 84%; }
.coord[data-arranged='true'] .tile[data-tile='onboard']  { left: 62%; top: 84%; }

/* Tracing a task lifts it and its route. */
.tile[aria-pressed='true'] { border-color: var(--eva); background: #17281e; box-shadow: 0 0 0 1px var(--eva); }
.coord[data-traced] .tile:not([aria-pressed='true']):not(.is-related) { opacity: .38; }
.coord[data-traced] .tile.is-related { border-color: #88dda65c; }

/* Progress signals returning to the goal. */
.coord-signal { fill: var(--eva); opacity: 0; }
.coord[data-flow='true'] .coord-signal { opacity: 1; }

.coord-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 10px; }
.quiet-btn {
  padding: 8px 14px; min-height: 40px; background: transparent; border: 1px solid var(--hairline);
  color: var(--body); font: inherit; font-size: 13px; cursor: pointer;
}
.quiet-btn:hover { border-color: var(--eva); color: var(--eva); }
.coord-switch { display: inline-flex; margin-left: auto; border: 1px solid var(--hairline); }
.coord-switch button {
  padding: 8px 14px; min-height: 40px; background: transparent; border: 0;
  color: var(--body); font: inherit; font-size: 13px; cursor: pointer;
}
.coord-switch button[aria-pressed='true'] { background: var(--eva); color: var(--on-primary); font-weight: 600; }

/* --- phone: recompose vertically rather than shrink --- */
@media (max-width: 47.99rem) {
  .coord-stage { aspect-ratio: 360 / 560; }
  .tile { width: 116px; padding: 7px 9px; }
  .tile-name { font-size: 12px; }
  .coord-goal { top: 8%; padding: 8px 14px; }
  .coord-goal span { font-size: 17px; }
  .coord-zone { top: 76%; left: 5%; right: 5%; }

  .tile[data-tile='api']      { left: 26%; top: 24%; }
  .tile[data-tile='api2']   { left: 68%; top: 38%; }
  .tile[data-tile='tests']    { left: 72%; top: 16%; }
  .tile[data-tile='docs']     { left: 30%; top: 52%; }
  .tile[data-tile='settings'] { left: 72%; top: 62%; }
  .tile[data-tile='onboard']  { left: 28%; top: 76%; }

  .coord[data-arranged='true'] .tile[data-tile='api']      { left: 50%; top: 28%; }
  .coord[data-arranged='true'] .tile[data-tile='api2']   { left: 50%; top: 28%; }
  .coord[data-arranged='true'] .tile[data-tile='tests']    { left: 50%; top: 45%; }
  .coord[data-arranged='true'] .tile[data-tile='docs']     { left: 50%; top: 62%; }
  .coord[data-arranged='true'] .tile[data-tile='settings'] { left: 30%; top: 86%; }
  .coord[data-arranged='true'] .tile[data-tile='onboard']  { left: 70%; top: 86%; }
  .coord-switch { margin-left: 0; }
}

/* Reduced motion: no travel, no signals; the organised state is simply shown. */
@media (prefers-reduced-motion: reduce) {
  .tile, .coord-goal, .coord-zone, .coord-links path { transition: none !important; }
  .coord-signal { display: none; }
}

/* ==========================================================================
   Focus stage. A priority ladder: size and position carry the ranking, so the
   composition differs from the coordination scene's goal-and-lanes.
   ========================================================================== */
.pstage { margin-bottom: 4px; }
.pstage-frame {
  /* Deep enough for three stacked workstreams on the left and the bug pair
     below them, so no connector has to run past a node on its way out. */
  position: relative; width: 100%; aspect-ratio: 900 / 520;
  border: 1px solid var(--hairline);
  background: linear-gradient(180deg, #16201a55, transparent 60%);
  overflow: hidden;
}
.pstage-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.pstage-links path { fill: none; stroke-width: 1.6; opacity: 1; transition: opacity 380ms; }
.pstage-links path.is-block { stroke: var(--warn); stroke-dasharray: 5 4; }
.pstage-links path.is-dep { stroke: #91bff36b; }


/* The thing being blocked. */
.release-mark {
  position: absolute; left: 88%; top: 26%; transform: translate(-50%, -50%);
  padding: 8px 12px; border: 1px solid var(--warn); background: #241d10;
  opacity: 1; transition: opacity 380ms, border-color 300ms;
}
.release-mark span { font-family: var(--font-display); font-size: 15px; color: var(--warn); line-height: 1; }
/* Only the blocked release reddens; the other one carries on unaffected. */
.pstage[data-blocked='true'] .release-mark[data-release='r24'] { border-color: var(--danger); }
.pstage[data-blocked='true'] .release-mark[data-release='r24'] span { color: var(--danger-text); }

/* A release that has everything it needs turns green. */
.release-mark[data-done='true'] { border-color: var(--eva); background: #12211a; }
.release-mark[data-done='true'] span { color: var(--eva); }

/* Distribution appears behind the finished release. */
.dist-mark {
  position: absolute; transform: translate(-50%, -50%) scale(.9); text-align: center;
  padding: 8px 12px; border: 1px solid var(--eva); background: #12211a;
  opacity: 0; visibility: hidden;
  transition: opacity 420ms, transform 420ms var(--ease-out), visibility 0s linear 420ms;
}
.dist-mark span {
  display: block; font-family: var(--font-display); font-size: 14px;
  color: var(--eva); line-height: 1;
}
.pstage[data-shipped='true'] .dist-mark {
  opacity: 1; visibility: visible; transform: translate(-50%, -50%) scale(1);
  transition: opacity 420ms, transform 420ms var(--ease-out), visibility 0s;
}
.pstage-links path.is-ship { stroke: var(--eva); }


.tile[data-ftile] { transition-duration: 700ms; }
.pstage[data-ranked='true'] .tile[data-ftile='api'] { border-color: var(--eva); background: #17281e; }
.pstage[data-ranked='true'] .tile[data-ftile='settings'],
.pstage[data-ranked='true'] .tile[data-ftile='onboard'] { opacity: .6; }
.tile[data-ftile][aria-pressed='true'] { border-color: var(--eva); box-shadow: 0 0 0 1px var(--eva); }

.focus-detail {
  font-size: 13px; line-height: 1.7; color: var(--body); margin-top: 6px;
  padding-left: 12px; border-left: 2px solid var(--eva); max-width: 60ch;
}
.focus-detail[hidden] { display: none; }

@media (max-width: 47.99rem) {
  /* The nodes are smaller now, so the frame that all three tabs share can be
     shorter -- which is what was leaving Decisions floating in dead space. */
  .pstage-frame { aspect-ratio: 360 / 620; }
  .slot-now   { left: 50%; top: 40%; }
  .slot-next  { left: 50%; top: 58%; }
  .slot-later { left: 50%; top: 92%; }
  .dist-mark { padding: 7px 10px; }
  .dist-mark span { font-size: 13px; }
  .reason { font-size: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .tile[data-ftile], .release-mark, .slot, .reason, .pstage-links path { transition: none !important; }
}

/* ==========================================================================
   Blockers. Two routes, one gate. Signals travel the connectors; the gate stops
   one route while the other keeps moving. Each node shows one state, never two.
   ========================================================================== */
.gate-scene { margin-bottom: 4px; }
.gate-stage { display: grid; gap: 22px; }
.lane {
  position: relative; display: flex; align-items: center; gap: 0; flex-wrap: nowrap;
  padding: 26px 14px 14px; border: 1px solid var(--hairline); background: #111814;
}
.lane-quiet { background: #0f1512; }
.lane-tag {
  position: absolute; left: 14px; top: 7px; font-size: 9px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}

.gnode {
  flex: 0 0 auto; min-width: 0; padding: 9px 12px; border: 1px solid var(--hairline);
  background: #141c17; text-align: left;
}
.gnode-name { display: block; font-size: 12px; font-weight: 600; color: var(--foreground); line-height: 1.25; }
/* ONE state element per node. Its text is rewritten; nothing is toggled. */
.gnode-state { display: block; font-size: 10px; line-height: 1.4; margin-top: 2px; color: var(--muted); }
.gnode[data-status='done']    { border-color: #88dda659; }
.gnode[data-status='done']    .gnode-state { color: var(--eva); }
.gnode[data-status='blocked'] { border-color: var(--danger); }
.gnode[data-status='blocked'] .gnode-state { color: var(--danger-text); }
.gnode[data-status='waiting'] { border-color: var(--warn); border-style: dashed; }
.gnode[data-status='waiting'] .gnode-state { color: var(--warn); }
.gnode[data-status='moving']  { border-color: var(--eva); }
.gnode[data-status='moving']  .gnode-state { color: var(--eva); }

/* Connectors carry the travelling signal. */
.conn { position: relative; flex: 1 1 auto; min-width: 26px; height: 2px; background: var(--hairline); }
.conn .pulse {
  position: absolute; top: 50%; left: 0; width: 6px; height: 6px; margin-top: -3px;
  border-radius: 50%; background: var(--eva);
  animation: gate-flow 1.9s linear infinite;
}
@keyframes gate-flow { from { left: 0; opacity: 0; } 12%, 80% { opacity: 1; } to { left: 100%; opacity: 0; } }
.gate-scene[data-state='blocked'] .lane[data-lane='a'] .pulse { animation-play-state: paused; opacity: 0; }
.gate-scene[data-state='blocked'] .lane[data-lane='a'] .conn:not(.has-gate) { background: #4a3a1f; }

/* The gate itself. */
.conn.has-gate { min-width: 54px; }
.gate {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 20px; height: 26px; display: grid; place-items: center;
  border: 1px solid var(--hairline); background: var(--canvas-deep); transition: border-color 260ms;
}
.gate b { display: block; width: 8px; height: 2px; background: var(--muted); transition: transform 320ms, background 260ms; }
.gate-scene[data-state='blocked'] .gate { border-color: var(--danger); }
.gate-scene[data-state='blocked'] .gate b { background: var(--danger); transform: rotate(90deg) scaleX(3.4); }
.gate-scene[data-state='open'] .gate,
.gate-scene[data-state='resumed'] .gate { border-color: var(--eva); }
.gate-scene[data-state='open'] .gate b,
.gate-scene[data-state='resumed'] .gate b { background: var(--eva); }

.signoff-btn {
  display: inline-flex; align-items: center; gap: 10px; padding: 9px 14px; min-height: 44px;
  border: 1px solid var(--edn); background: #1d1a12; color: var(--edn);
  font: inherit; font-size: 13px; cursor: pointer;
}
.signoff-btn:hover { background: #2a2416; }
.signoff-btn[disabled] { opacity: .45; cursor: default; }

/* --- phone: routes stack and run downward --- */
@media (max-width: 47.99rem) {
  .lane { flex-direction: column; align-items: stretch; gap: 0; padding: 26px 12px 12px; }
  .gnode { width: 100%; }
  .conn { width: 2px; height: 26px; min-width: 0; margin: 0 auto; flex: 0 0 auto; }
  .conn.has-gate { height: 46px; min-width: 0; }
  .conn .pulse { left: 50%; margin-left: -3px; top: 0; margin-top: 0; animation-name: gate-flow-y; }
  @keyframes gate-flow-y { from { top: 0; opacity: 0; } 12%, 80% { opacity: 1; } to { top: 100%; opacity: 0; } }
}

@media (prefers-reduced-motion: reduce) {
  .conn .pulse { animation: none; opacity: 1; left: 50%; }
  .gate, .gate b { transition: none !important; }
}

/* ==========================================================================
   Decisions. A fork: one route in, two routes out, both held at a gate that
   only a person opens. The composition is a branch, not a pair of cards.
   ========================================================================== */
.fork-scene { margin-bottom: 4px; }
.fork-stage {
  position: relative; width: 100%; aspect-ratio: 900 / 380;
  border: 1px solid var(--hairline); background: linear-gradient(90deg, #16201a44, transparent 55%);
  overflow: hidden;
}
.fork-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.fork-links path { fill: none; stroke: var(--hairline); stroke-width: 2; opacity: 0; transition: opacity 380ms, stroke 300ms; }
.fork-links path.is-live { opacity: 1; }
.fork-links path.is-chosen { stroke: var(--eva); stroke-width: 3; }
.fork-links path.is-faded { opacity: .28; }

.fnode {
  position: absolute; transform: translate(-50%, -50%); padding: 9px 12px;
  border: 1px solid var(--hairline); background: #141c17; min-width: 0;
}
.fnode-name { display: block; font-size: 12px; font-weight: 600; color: var(--foreground); line-height: 1.25; }
.fnode-state { display: block; font-size: 10px; color: var(--muted); margin-top: 2px; }
.fnode-start { left: 8%; top: 50%; }
.fnode-fork {
  position: absolute; left: 30%; top: 50%; width: 14px; height: 14px;
  transform: translate(-50%, -50%) rotate(45deg); border: 2px solid var(--edn); background: #1d1a12;
}

/* Gates sit on each branch and stay shut until a person opens one. */
.fgate {
  position: absolute; transform: translate(-50%, -50%); width: 22px; height: 26px;
  border: 1px solid var(--edn); background: var(--canvas-deep);
  opacity: 0; transition: opacity 340ms, border-color 260ms, background 260ms;
}
.fgate::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 10px; height: 2px;
  margin: -1px 0 0 -5px; background: var(--edn); transform: rotate(90deg) scaleX(3.6);
  transition: transform 320ms, background 260ms;
}
.fork-scene[data-phase='await'] .fgate,
.fork-scene[data-phase='chosen'] .fgate { opacity: 1; }
.fgate[data-open='true'] { border-color: var(--eva); }
.fgate[data-open='true']::before { background: var(--eva); transform: rotate(0deg) scaleX(1); }

.gate-label {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  padding: 3px 9px; border: 1px solid var(--edn); background: #1d1a12; color: var(--edn);
  font-size: 10px; letter-spacing: .07em; text-transform: uppercase; white-space: nowrap;
  opacity: 0; transition: opacity 340ms;
}
.fork-scene[data-phase='await'] .gate-label { opacity: 1; animation: gate-breathe 2.2s ease-in-out infinite; }
@keyframes gate-breathe { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }

/* Routes are the choice controls themselves. */
.froute {
  position: absolute; transform: translate(-50%, -50%); display: grid; gap: 3px;
  width: 200px; padding: 11px 13px; text-align: left; cursor: pointer;
  border: 1px solid var(--hairline); background: #121a15; color: var(--foreground);
  opacity: 0; transition: opacity 380ms, border-color 240ms, background 240ms, box-shadow 240ms;
}
.fork-scene[data-phase='branch'] .froute,
.fork-scene[data-phase='advise'] .froute,
.fork-scene[data-phase='await'] .froute,
.fork-scene[data-phase='chosen'] .froute { opacity: 1; }
.froute-key { font-size: 10px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
/* The option text wraps inside its box. Something upstream sets nowrap on it,
   which let a long label run straight out through the border. */
.froute-name {
  font-size: 13px; font-weight: 600; line-height: 1.3;
  white-space: normal; overflow-wrap: break-word;
}
.froute-conseq { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--body); }
.rel { width: 9px; height: 11px; border: 1px solid var(--adm); background: #16212c; flex: 0 0 auto; }
.froute .tag-rec { justify-self: start; margin-top: 3px; }
.fork-scene[data-phase='advise'] .froute.is-rec,
.fork-scene[data-phase='await'] .froute.is-rec { border-color: #88dda67a; }
.froute:hover { border-color: #88dda67a; }
.froute[aria-pressed='true'] { border-color: var(--eva); background: #17281e; box-shadow: 0 0 0 1px var(--eva); }
.froute[aria-pressed='true'] .rel { border-color: var(--eva); background: #16241c; }
/* The route not taken recedes but stays selectable. */
.fork-scene[data-chosen] .froute:not([aria-pressed='true']) { opacity: .42; }

.fork-details { margin-top: 8px; font-size: 13px; color: var(--body); }
.fork-details summary { cursor: pointer; color: var(--eva); padding: 6px 0; min-height: 32px; }
.fork-details p { margin-top: 4px; max-width: 62ch; line-height: 1.7; }

@media (max-width: 47.99rem) {
  /* Shorter stage and smaller boxes: the old one left a screen's worth of empty
     space above and below the two options. */
  .fork-stage { aspect-ratio: 360 / 430; }
  .froute {
    /* proportional, so the gap between the two options holds on any phone
       instead of closing up as the frame narrows */
    width: 41%; padding: 8px 10px; gap: 2px;
    transform: translate(-50%, 0);        /* hang from a shared top edge */
  }
  .froute-key { font-size: 8.5px; }
  .froute-name { font-size: 10.5px; }
  .froute-conseq { font-size: 9px; }
  .froute .tag-rec { font-size: 8.5px; }
  .fnode { padding: 7px 9px; }
  .fnode-name { font-size: 10.5px; }
  .fnode-state { font-size: 8.5px; }
  .gate-label { font-size: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .froute, .fgate, .gate-label, .fork-links path, .fnode { transition: none !important; }
  .fork-scene[data-phase='await'] .gate-label { animation: none; opacity: 1; }
}

/* ==========================================================================
   ADM execution. Three compact workspaces, each showing a different kind of
   work being made, with finished artifacts landing in one shared review tray.
   ========================================================================== */
.adm-scene { max-width: none; }
.adm-top { display: grid; justify-items: center; gap: 0; }
.adm-eva {
  display: flex; flex-direction: column; align-items: center; padding: 8px 18px;
  border: 1px solid var(--eva); background: #163322;
}
.adm-eva span { font-family: var(--font-display); font-size: 20px; color: var(--eva); line-height: 1; }
.adm-eva small { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--body); }
.adm-fan { position: relative; width: 100%; height: 34px; }
.adm-fan i {
  position: absolute; top: 0; bottom: 0; width: 1px; background: #91bff34d;
}
.adm-fan i:nth-child(1) { left: 16.6%; }
.adm-fan i:nth-child(2) { left: 50%; }
.adm-fan i:nth-child(3) { left: 83.3%; }
.adm-scene[data-phase='running'] .adm-fan i,
.adm-scene[data-phase='done'] .adm-fan i { background: var(--adm); }

.adm-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.ws {
  display: grid; gap: 8px; padding: 12px; border: 1px solid var(--hairline);
  background: #111814; min-width: 0; transition: border-color 300ms;
}
.ws[data-state='working'] { border-color: #91bff36e; }
.ws[data-state='ready']   { border-color: var(--eva); }
/* A failing suite goes red round its whole frame; the implementation that has
   to answer for it goes amber, and the suite cools to amber behind it while it
   waits for the fix. */
.ws[data-state='failed']  { border-color: var(--danger); background: #17100f; }
.ws[data-state='fixing']  { border-color: var(--warn); }
.ws[data-state='waiting'] { border-color: var(--warn); transition: border-color 1400ms ease, background 1400ms ease; }
.ws-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ws-kind { font-size: 12px; font-weight: 600; color: var(--foreground); }
.ws-who  { font-size: 9px; letter-spacing: .06em; text-transform: uppercase; color: var(--adm); }
.ws-body { min-height: 74px; padding: 8px; background: var(--canvas-deep); border: 1px solid #212b25; }
.ws-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.ws-out { font-size: 10px; color: var(--muted); overflow-wrap: anywhere; }
.ws-state { font-size: 10px; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.ws[data-state='working'] .ws-state { color: var(--adm); }
.ws[data-state='ready'] .ws-state { color: var(--eva); }
.ws[data-state='failed'] .ws-state { color: var(--danger-text); }
.ws[data-state='fixing'] .ws-state,
.ws[data-state='waiting'] .ws-state { color: var(--warn); }

/* Implementation: a diff assembling line by line. */
.ws-impl { display: grid; gap: 5px; align-content: start; }
.ws-impl i {
  display: block; height: 5px; background: #22302a; opacity: .35;
  transition: opacity 260ms, background 260ms, width 320ms var(--ease-out);
}
.ws-impl i[data-row='0'] { width: 62%; }
.ws-impl i[data-row='1'] { width: 84%; }
.ws-impl i[data-row='2'] { width: 46%; }
.ws-impl i[data-row='3'] { width: 74%; }
.ws-impl i[data-row='4'] { width: 55%; }
.ws-impl i[data-on='1'] { opacity: 1; background: var(--eva); }

/* Tests: a grid of checks turning over. */
/* The cells are square, so a full-width column made them enormous on a wide
   screen and pushed the whole ADM frame past the fold. Cap the cell. */
.ws-tests {
  display: grid; grid-template-columns: repeat(4, minmax(0, 38px)); gap: 5px;
  align-content: start; justify-content: center;
}
.ws-tests i {
  display: block; aspect-ratio: 1; border: 1px solid #2a3630; background: transparent;
  transition: background 220ms, border-color 220ms;
}
.ws-tests i[data-cell-state='run']  { border-color: var(--warn); background: #2a2214; }
.ws-tests i[data-cell-state='pass'] { border-color: var(--eva); background: #17301f; }
.ws-tests i[data-cell-state='fail'] { border-color: var(--danger); background: #2e1614; }

/* Documentation: an outline filling with sections. */
.ws-docs { display: grid; gap: 6px; align-content: start; }
.ws-docs i {
  display: block; height: 5px; width: 0; background: var(--adm); opacity: .8;
  transition: width 420ms var(--ease-out);
}
.ws-docs i.doc-title { height: 8px; background: var(--edn); }
.ws-docs i[data-on='1'][data-line='0'] { width: 52%; }
.ws-docs i[data-on='1'][data-line='1'] { width: 92%; }
.ws-docs i[data-on='1'][data-line='2'] { width: 78%; }
.ws-docs i[data-on='1'][data-line='3'] { width: 88%; }
.ws-docs i[data-on='1'][data-line='4'] { width: 64%; }

/* One shared tray receives the finished work. */
.adm-tray {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding: 11px 13px; border: 1px dashed var(--hairline); background: #0f1512;
  transition: border-color 300ms;
}
.adm-scene[data-phase='done'] .adm-tray { border-color: var(--eva); border-style: solid; }
.tray-label { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.tray-slots { display: flex; flex-wrap: wrap; gap: 8px; min-height: 26px; align-items: center; }
.artifact {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px;
  border: 1px solid var(--eva); background: #16241c; color: var(--eva); font-size: 11px;
  animation: artifact-in 420ms var(--ease-out) both;
}
.artifact::before { content: ''; width: 7px; height: 9px; border: 1px solid currentColor; }
@keyframes artifact-in { from { opacity: 0; transform: translateY(-10px) scale(.9); } to { opacity: 1; transform: none; } }

@media (max-width: 47.99rem) {
  .adm-grid { grid-template-columns: 1fr; gap: 10px; }
  .adm-fan { height: 22px; }
  .adm-fan i:nth-child(1), .adm-fan i:nth-child(3) { display: none; }
  .ws-body { min-height: 62px; }
}

@media (prefers-reduced-motion: reduce) {
  .ws-impl i, .ws-tests i, .ws-docs i, .ws, .adm-tray { transition: none !important; }
  .artifact { animation: none; }
}

/* ==========================================================================
   Compact "how it works" sequence: four short labels on one line, replacing
   the four-column paragraph strip.
   ========================================================================== */
.howflow-row {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0;
}
.howflow-row li {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 14px 18px 14px 0; min-width: 0;
}
.howflow-row li + li { padding-left: 26px; }
/* connector between steps */
.howflow-row li + li::before {
  content: ''; position: absolute; left: 0; top: 50%; width: 14px; height: 1px;
  background: var(--hairline);
}
.howflow-row li + li::after {
  content: ''; position: absolute; left: 11px; top: 50%; width: 5px; height: 5px;
  margin-top: -2px; border-top: 1px solid var(--edn); border-right: 1px solid var(--edn);
  transform: rotate(45deg) translateY(-1px);
}
.howflow-n {
  font-family: var(--font-display); font-size: 22px; line-height: 1; color: var(--edn); flex: 0 0 auto;
}
.howflow-row strong { font-size: 13px; font-weight: 600; color: var(--foreground); line-height: 1.3; }

@media (max-width: 47.99rem) {
  .howflow-row { grid-template-columns: 1fr; }
  .howflow-row li { padding: 10px 0 10px 0; }
  .howflow-row li + li { padding-left: 0; padding-top: 18px; }
  .howflow-row li + li::before { left: 11px; top: 4px; width: 1px; height: 10px; }
  .howflow-row li + li::after { left: 9px; top: 12px; transform: rotate(135deg); }
}

/* ==========================================================================
   Full-bleed graphics and the run indicator. The bleed cancels the section's
   own horizontal padding rather than using vw units, which include the
   scrollbar and previously pushed the page sideways.
   ========================================================================== */
/* Graphics align to the hero's content box, which sets the page's width for
   everything else. They previously bled past it to the viewport edge, which put
   them 40px wider than every heading on the page. */
.edn-graphic.is-bleed { margin-inline: 0; width: 100%; }

/* A 2px rule across the top of each scene, filling left to right as it plays. */
/* The indicator rides the inside of the frame's top edge. */
.scene-bar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  height: 2px; background: #ffffff0f; overflow: hidden; pointer-events: none;
}
.scene-bar i {
  display: block; height: 100%; width: 0; background: var(--eva);
}
@keyframes edn-bar { from { width: 0; } to { width: 100%; } }

@media (prefers-reduced-motion: reduce) {
  .scene-bar i { animation: none !important; width: 100%; }
}

/* Blockers and ADM had no single rectangle; give them one so the run indicator
   has a frame to sit in, and drop the now-duplicated inner borders. */
.gate-stage {
  position: relative; border: 1px solid var(--hairline); background: #101613;
  padding: 18px; gap: 14px;
  /* This scene is shorter than its neighbours but shares their frame, so its
     two lanes sit in the middle of it rather than clinging to the top. */
  align-content: center;
}
.lane { border: 0; background: #141c17; }
.lane-quiet { background: #121815; }

.adm-frame {
  position: relative; border: 1px solid var(--hairline); background: #101613;
  padding: 18px; display: grid; gap: 12px;
}
.adm-tray { margin-top: 0; }

@media (max-width: 47.99rem) {
  .gate-stage, .adm-frame { padding: 14px; }
}

/* While a resize is in flight the nodes must not animate to their new places,
   or the links get drawn against positions the tiles have not reached yet. */
.is-resizing .tile,
.is-resizing .coord-goal,
.is-resizing .coord-zone,
.is-resizing .reason,
.is-resizing .release-mark,
.is-resizing .dist-mark,
.is-resizing .froute,
.is-resizing .fnode,
.is-resizing .fgate,
.is-resizing .gate-label,
.is-resizing .coord-links path,
.is-resizing .pstage-links path,
.is-resizing .fork-links path { transition: none !important; }

/* Tests carries no glyph, so its label spans the whole tile. */
/* Without a glyph the tile is a single column. `grid-column: 2` on the owner
   chip was creating an implicit second track, which put the name and its
   subtitle side by side instead of stacked. */
.tile.no-icon { grid-template-columns: minmax(0, 1fr); }
.tile.no-icon .tile-name,
.tile.no-icon .tile-sub,
.tile.no-icon .tile-own { grid-column: 1; }
@media (max-width: 47.99rem) { .coord-zone { top: 66%; bottom: 12%; } }

/* ==========================================================================
   Focus scene. Two workstreams build; a Class A bug arrives and blocks the
   release; the fix and its regression test go first; the paused work resumes.
   ========================================================================== */
.wnode {
  position: absolute; transform: translate(-50%, -50%); width: 190px;
  display: grid; gap: 4px; padding: 11px 13px;
  border: 1px solid var(--hairline); background: #121a15;
  transition: opacity 360ms, border-color 300ms, background 300ms;
}
.wnode-name { font-size: 13px; font-weight: 600; color: var(--foreground); line-height: 1.2; }
.wnode-sub { font-size: 10px; color: var(--muted); line-height: 1.3; }
.wnode-meter { display: block; height: 4px; background: #22302a; overflow: hidden; margin-top: 2px; }
.wnode-meter i { display: block; height: 100%; width: 0; background: var(--adm); transition: width 620ms linear; }
.wnode-state { font-size: 10px; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }

.wnode[data-state='working'] { border-color: #91bff36e; }
.wnode[data-state='working'] .wnode-state { color: var(--adm); }
.wnode[data-state='paused'] { opacity: .45; border-color: var(--hairline); }
.wnode[data-state='paused'] .wnode-meter i { background: var(--muted); }
.wnode[data-state='paused'] .wnode-state { color: var(--muted); }
.wnode[data-state='done'] { border-color: var(--eva); }
.wnode[data-state='done'] .wnode-meter i { background: var(--eva); }
.wnode[data-state='done'] .wnode-state { color: var(--eva); }

/* The bug, its regression test and the release test all arrive mid-run. */
.wnode[data-kind='bug'], .wnode[data-kind='bugtest'], .wnode[data-kind='reltest'] {
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity 360ms, visibility 0s linear 360ms, border-color 300ms;
}
.pstage[data-bug='true'] .wnode[data-kind='bug'],
.pstage[data-bug='true'] .wnode[data-kind='bugtest'],
.pstage[data-tested='true'] .wnode[data-kind='reltest'] {
  opacity: 1; visibility: visible; transition: opacity 360ms, visibility 0s, border-color 300ms;
}
.wnode[data-kind='bug'] { border-color: var(--danger); background: #241413; }
.wnode[data-kind='bug'] .wnode-name { color: var(--danger-text); }
.wnode[data-kind='bug'] .wnode-meter i { background: var(--danger); }
.wnode[data-kind='bug'][data-state='done'] { border-color: var(--eva); }
.wnode[data-kind='bug'][data-state='done'] .wnode-meter i { background: var(--eva); }

/* Links: normal work in blue, the blocking pair in red until it clears. */
.pstage-links path.is-block { stroke: var(--danger); stroke-dasharray: 5 4; }
.pstage-links path.is-work { stroke: #91bff355; }

@media (max-width: 47.99rem) {
  /* A fifth smaller again, so more rows clear one another on a phone. */
  .wnode { width: 112px; padding: 6px 8px; gap: 2px; }
  .wnode-name { font-size: 10.5px; }
  .wnode-sub { font-size: 8px; }
  .wnode-state { font-size: 8px; }
  .wnode-meter { height: 3px; }
  .release-mark { padding: 6px 9px; }
  .release-mark span { font-size: 13px; }
  .dist-mark span { font-size: 12px; }
  .wnode-name { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .wnode, .wnode-meter i { transition: none !important; }
}

/* ==========================================================================
   One section per screen. The runtime measures each section and only turns
   snapping on when every one of them fits the viewport; below that the page
   scrolls normally, so a short window never traps content off-screen.
   ========================================================================== */
/* body carries an overflow-x, which is what propagates to the viewport on this
   theme. Some browsers then read the snap type from body rather than the root,
   so it is declared on both. */
html.edn-snap, html.edn-snap body { scroll-snap-type: y mandatory; }
html.edn-snap [data-elementor-type] > .e-con {
  scroll-snap-align: start;
  scroll-snap-stop: always;            /* one section per gesture, no free run */
  min-height: var(--edn-vh, 100vh);
}
/* The closing strip is short; it rides at the foot of the last screen rather
   than claiming one of its own. */
html.edn-snap [data-elementor-type] > .e-con:last-child {
  min-height: 0; scroll-snap-align: end; scroll-snap-stop: normal;
}
@media (prefers-reduced-motion: no-preference) {
  html.edn-snap { scroll-behavior: smooth; }
}

/* A section that would otherwise overrun the screen gives up its own spacing
   first -- padding, then the room inside the content-sized frames -- before any
   graphic is asked to shrink. */
.edn-tight > .e-con-inner { padding-block: 40px !important; }
.edn-tight .gate-stage { padding: 12px; gap: 10px; }
.edn-tight .lane { padding: 26px 10px 10px; }   /* room for the lane label */
.edn-tight .adm-frame { padding: 12px; gap: 8px; }
.edn-tight .adm-grid { gap: 8px; }
.edn-tight .ws { padding: 9px; gap: 6px; }
.edn-tight .ws-body { min-height: 56px; }
.edn-tight .adm-tray { padding: 8px 11px; }
.edn-tight .adm-fan { height: 22px; }
.edn-tight .adm-eva { padding: 6px 16px; }
/* The sign-off control is the tallest thing any tab panel carries below its
   frame, and every tab pays for it once the three share one height. */
.edn-tight .coord-controls { margin-top: 6px; gap: 8px; }
.edn-tight .signoff-btn { min-height: 34px; padding: 6px 12px; }
.edn-tight .scene-head { margin-bottom: 8px; }
/* The pipeline gives up its own spacing so its section still fits one screen. */
.edn-tight .pipe-frame { padding: 14px; gap: 12px; }
.edn-tight .pipe-steps { gap: 5px; }
.edn-tight .pipe-steps span,
.edn-tight .pipe-steps button { padding: 6px 12px 6px 18px; font-size: 12px; }
.edn-tight .pipe-col { padding: 11px 13px 12px; }
.edn-tight .pipe-kind { margin-bottom: 8px; }
.edn-tight .pipe-detail { min-height: 150px; padding-top: 12px; }
.edn-tight .pipe-detail strong { font-size: 18px; margin-bottom: 8px; }
.edn-tight .e-n-tabs-content > * { padding-top: 12px; }

/* A tight section also gives up a little of its heading scale and the padding
   around the tab strip, which is cheaper than taking the height out of the
   graphic. Only sections that would otherwise overrun the screen get this. */
.edn-tight .elementor-heading-title { font-size: .8em; }
.edn-tight .elementor-widget-text-editor p { margin-bottom: 0; line-height: 1.5; }
.edn-tight > .e-con-inner { row-gap: 8px; }
.edn-tight .e-n-tab-title { padding-block: 8px; }
.edn-tight > .e-con-inner > .e-con:last-child { margin-top: 12px; }
.edn-tight .elementor-widget-n-tabs { --n-tabs-gap: 12px; }

/* A Focus stage fitted to the screen loses height, not rows, so the nodes get a
   compact form: same information, less box around it. */
.pstage.is-short .wnode {
  width: 190px; padding: 7px 10px; gap: 3px 10px;
  grid-template-columns: auto 1fr; align-items: center;
}
.pstage.is-short .wnode-name  { grid-column: 1; grid-row: 1; font-size: 12px; white-space: nowrap; }
.pstage.is-short .wnode-sub   { grid-column: 2; grid-row: 1; font-size: 9px; text-align: right; white-space: nowrap; }
.pstage.is-short .wnode-meter { grid-column: 1; grid-row: 2; width: 100%; height: 3px; margin: 0; }
.pstage.is-short .wnode-state { grid-column: 2; grid-row: 2; font-size: 9px; text-align: right; }
.pstage.is-short .release-mark { padding: 6px 10px; }
.pstage.is-short .release-mark span { font-size: 13px; }
.pstage.is-short .dist-mark { padding: 6px 10px; }
.pstage.is-short .dist-mark span { font-size: 12px; }

/* ==========================================================================
   Phone sizing. The section titles were rendering at their desktop size, the
   caption reserved more room than it needed, and the tab strip sat too far
   below the heading.
   ========================================================================== */
@media (max-width: 47.99rem) {

  /* The caption sits against its rule rather than floating at the top of a box
     that is taller than the words in it. */
  .edn-graphic .scene-head { margin-bottom: 12px; }
  .edn-graphic .scene-label { min-height: 2.1em; display: flex; align-items: center; }
  .edn-graphic .scene-rerun { width: 26px; height: 26px; font-size: 14px; }

  /* Less air between the section heading and the Focus / Blockers / Decisions
     strip. */
  #eva > .e-con-inner > .e-con:first-child { margin-bottom: 8px; }

  /* The page opens with room above the first eyebrow. */
  #edn-hero > .e-con-inner { padding-top: 148px; }
}

/* Every section title takes the hero headline's size on anything narrower than
   a desktop. The hero sizes itself from its container; the sections share the
   same page gutter, so the viewport form of that expression lands on the same
   number. The min() keeps a wide phone or a tablet from going past the size the
   desktop layout uses. Elementor writes a per-element font-size for every
   heading widget, so this has to outrank it rather than out-specify it. */
@media (max-width: 63.99rem) {
  .elementor-widget-heading h2.elementor-heading-title {
    font-size: min(64px, clamp(2rem, calc((100vw - 48px) / 7), 6rem)) !important;
    line-height: 1 !important;
  }
}

@media (max-width: 47.99rem) {
  /* A phone stacks the three workstreams, so the ADM frame needs to give up
     more than a desktop one to share a screen with nothing else. */
  .edn-tight .ws { padding: 8px; gap: 5px; }
  .edn-tight .ws-body { min-height: 44px; padding: 6px; }
  .edn-tight .ws-tests { grid-template-columns: repeat(6, minmax(0, 22px)); }
  .edn-tight .adm-fan { height: 18px; }
  .edn-tight .adm-frame { padding: 10px; gap: 6px; }
  .edn-tight .adm-grid { gap: 6px; }
  .edn-tight .adm-tray { padding: 6px 10px; }
  .edn-tight .adm-eva { padding: 4px 14px; }

  /* The compact node's desktop width would put two of them past the edge of a
     phone-width frame, so the phone width wins here. */
  .pstage.is-short .wnode { width: 130px; }
}

/* The hero's opening line carries the same treatment as the readout title in
   the graphic beside it. */
.lede-title {
  display: block; margin-bottom: 8px;
  font-family: var(--font-display); font-size: 24px; font-weight: 400;
  text-transform: uppercase; line-height: 1.12; color: var(--foreground);
}
.lede-body { display: block; }

/* Same breakpoint as the section titles: a phone in landscape reports well over
   768px, so the narrower breakpoint never reached it. */
@media (max-width: 63.99rem) {
  /* The supporting sentence steps back a little, and the opening line goes:
     the headline above it already says it. */
  .lede-body { font-size: 80%; }
  .lede-title { display: none; }
}

@media (max-width: 47.99rem) {
  /* A little air between the logo and the headline in the stacked hero lockup. */
  #edn-hero-title .elementor-heading-title { margin-top: 16px; }
}

/* ==========================================================================
   How it works: the same lifecycle organised two ways, as two separate panels.
   Each column is a run of stages threaded on a rail, not a row of buttons --
   the EDN rail fills as the pipeline advances.
   ========================================================================== */
.pipe-frame {
  position: relative; border: 1px solid var(--hairline); background: #101613;
  padding: 22px; display: grid; gap: 20px;
}
/* Two distinct panels with a gap between them, so which column is which is
   never in question. */
.pipe-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.pipe-col { padding: 14px 16px 16px; border: 1px solid var(--hairline); background: #0e1411; }
.pipe-new { border-color: #88dda647; background: #111a15; }

.pipe-kind {
  margin: 0 0 12px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
.pipe-new .pipe-kind { color: var(--eva); }

/* The rail: one line threading the stages, with a node at each stop. */
.pipe-steps {
  list-style: none; margin: 0; padding: 0 0 0 20px; display: grid; gap: 0;
  position: relative;
}
.pipe-steps::before {
  content: ''; position: absolute; left: 4px; top: 14px; bottom: 14px; width: 1px;
  background: var(--hairline);
}
.pipe-new .pipe-steps::before { background: #88dda63d; }
/* How far the pipeline has run. */
.pipe-new .pipe-steps::after {
  content: ''; position: absolute; left: 4px; top: 14px; width: 1px;
  height: var(--pipe-progress, 0px); background: var(--eva);
  transition: height 420ms var(--ease-out);
}
.pipe-steps li { display: block; }
.pipe-steps span,
.pipe-steps button {
  position: relative; display: block; width: 100%; text-align: left;
  font: inherit; font-size: 13px; line-height: 1.35; padding: 9px 0;
  border: 0; background: transparent; color: var(--body);
}
.pipe-old .pipe-steps span { color: var(--muted); }
.pipe-steps span::before,
.pipe-steps button::before {
  content: ''; position: absolute; left: -20px; top: 50%; transform: translateY(-50%);
  width: 9px; height: 9px; border-radius: 50%;
  border: 1px solid var(--hairline); background: #0e1411;
  transition: background 260ms, border-color 260ms, box-shadow 260ms;
}
.pipe-steps button { cursor: pointer; transition: color 260ms; }
.pipe-steps button:hover { color: var(--foreground); }
.pipe-steps button:hover::before { border-color: var(--eva); }
.pipe-steps button:focus-visible { outline: 2px solid var(--eva); outline-offset: 2px; }
/* Stages already run keep a lit node; the current one is filled. */
.pipe-new button[data-done='true']::before { border-color: var(--eva); background: #16241c; }
.pipe-new button[aria-pressed='true'] { color: var(--foreground); font-weight: 600; }
.pipe-new button[aria-pressed='true']::before {
  background: var(--eva); border-color: var(--eva); box-shadow: 0 0 0 3px #88dda62e;
}

.pipe-detail { border-top: 1px solid var(--hairline); padding-top: 16px; min-height: 190px; }
.pipe-detail strong {
  display: block; font-family: var(--font-display); font-size: 20px; font-weight: 400;
  text-transform: uppercase; line-height: 1.15; color: var(--foreground); margin-bottom: 10px;
}
.pipe-detail p { font-size: 13px; line-height: 1.7; color: var(--body); margin: 0 0 10px; }
.pipe-detail p:last-child { margin-bottom: 0; }
.pipe-detail { opacity: 1; transition: opacity 200ms ease; }
.pipe-detail[data-swap='out'] { opacity: 0; }

@media (max-width: 47.99rem) {
  .pipe-frame { padding: 14px; gap: 14px; }
  .pipe-cols { gap: 10px; }
  .pipe-col { padding: 11px 12px 12px; }
  .pipe-steps { padding-left: 17px; }
  .pipe-steps::before, .pipe-new .pipe-steps::after { left: 3px; }
  .pipe-steps span, .pipe-steps button { font-size: 11.5px; padding: 7px 0; }
  .pipe-steps span::before, .pipe-steps button::before { left: -17px; width: 7px; height: 7px; }
  .pipe-detail { min-height: 240px; padding-top: 12px; }
  .pipe-detail strong { font-size: 17px; }
  .pipe-detail p { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .pipe-steps button, .pipe-steps button::before, .pipe-detail,
  .pipe-new .pipe-steps::after { transition: none !important; }
  .pipe-detail { opacity: 1 !important; }
}

/* The hero's closing sentence starts a new line, but only where there is width
   for it to be a deliberate break rather than an orphan. */
.break-desk { display: none; }
@media (min-width: 64rem) { .break-desk { display: inline; } }

/* ==========================================================================
   Hover. The theme's reset paints every [type=button] magenta on hover and
   focus, which inside a graphic reads as an error rather than a selection.
   Replaced with a quiet green wash that keeps its label readable.
   ========================================================================== */
.edn-graphic [type="button"]:hover,
.edn-graphic [type="button"]:focus,
.edn-graphic [type="button"]:active,
.edn-graphic [type="submit"]:hover,
.edn-graphic [type="submit"]:focus {
  background-color: #1d3327;
  color: var(--foreground);
}

/* A pipeline stage highlights its label, not the whole column. */
.pipe-steps { padding-left: 10px; }
.pipe-steps span,
.pipe-steps button {
  width: fit-content; max-width: 100%;
  /* the extra left padding is the gap between the node on the rail and the
     label -- the selected node carries a 3px halo that eats into it */
  padding: 8px 12px 8px 18px;
}
.pipe-steps span::before,
.pipe-steps button::before { left: -10px; }

/* The lane label sits above its row rather than across the first node. It was
   inheriting a body line-height, which made an 9px label 26px tall and pushed
   it down onto the first node. */
.lane { padding-top: 30px; }
.lane-tag { top: 9px; line-height: 1; }

/* The node that waits on a person is the control. */
.gnode-act { cursor: default; text-align: left; font: inherit; }
.gnode-act[data-status='waiting'] { cursor: pointer; border-color: var(--edn); }
.gnode-act[data-status='waiting'] .gnode-state { color: var(--edn); }
.gnode-act:focus-visible { outline: 2px solid var(--eva); outline-offset: 2px; }

/* Tradeoffs live in the frame, open, under the node that raised the decision. */
.fork-note {
  position: absolute; transform: translate(-50%, -50%); width: 300px; max-width: 92%;
  /* left-anchored once there is a column to sit in, so it cannot hang off the
     edge of the frame the way a centred block does */
  text-align: left; border-left: 2px solid #dfbd7566; padding-left: 10px;
}
.fork-note strong {
  display: block; font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 5px;
}
.fork-note p { font-size: 11.5px; line-height: 1.55; color: var(--body); margin: 0 0 4px; }
.fork-note p:last-child { margin-bottom: 0; }
.fork-note p strong {
  display: inline; font-size: inherit; letter-spacing: 0; text-transform: none;
  color: var(--foreground); margin: 0;
}

@media (max-width: 47.99rem) {
  .pipe-steps { padding-left: 9px; }
  .pipe-steps span, .pipe-steps button { padding: 7px 10px 7px 16px; }
  .pipe-steps span::before, .pipe-steps button::before { left: -9px; }
  .fork-note { width: 92%; }
  .fork-note p { font-size: 10.5px; }
}

@media (min-width: 48rem) {
  .fork-note { transform: translate(0, -50%); }
}

/* ==========================================================================
   Decisions: size for the layout the runtime actually chose. The placement
   switches on the frame's own width (640) and the media query on the
   viewport (768); between those two the boxes were sized for one layout and
   positioned for the other, which cut the tradeoffs note off at the frame
   edge. The stage now says which layout it is in and the sizes follow it.
   ========================================================================== */
.fork-stage[data-layout='narrow'] .froute {
  width: 41%; padding: 8px 10px; gap: 2px; transform: translate(-50%, 0);
}
.fork-stage[data-layout='narrow'] .froute-key,
.fork-stage[data-layout='narrow'] .froute .tag-rec { font-size: 8.5px; }
.fork-stage[data-layout='narrow'] .froute-name { font-size: 10.5px; }
.fork-stage[data-layout='narrow'] .fnode { padding: 7px 9px; }
.fork-stage[data-layout='narrow'] .fnode-name { font-size: 10.5px; }
.fork-stage[data-layout='narrow'] .fnode-state { font-size: 8.5px; }
.fork-stage[data-layout='narrow'] .gate-label { font-size: 9px; }
.fork-stage[data-layout='narrow'] .fork-note { width: 92%; }
.fork-stage[data-layout='narrow'] .fork-note p { font-size: 10.5px; }

.fork-stage[data-layout='wide'] .froute {
  width: 200px; padding: 11px 13px; gap: 3px; transform: translate(-50%, -50%);
}
.fork-stage[data-layout='wide'] .froute-key { font-size: 10px; }
.fork-stage[data-layout='wide'] .froute .tag-rec { font-size: inherit; }
.fork-stage[data-layout='wide'] .froute-name { font-size: 13px; }
.fork-stage[data-layout='wide'] .fnode { padding: 9px 12px; }
.fork-stage[data-layout='wide'] .fnode-name { font-size: 12px; }
.fork-stage[data-layout='wide'] .fnode-state { font-size: 10px; }
.fork-stage[data-layout='wide'] .gate-label { font-size: 10px; }
.fork-stage[data-layout='wide'] .fork-note { width: 300px; }
.fork-stage[data-layout='wide'] .fork-note p { font-size: 11.5px; }

/* ==========================================================================
   Outbound links. The two brand marks and the footer credit are the only
   links on the page, so there is no established link style to inherit and the
   theme's default colour would read as foreign. They keep the colour of what
   they sit in and answer on hover in EVA green.
   ========================================================================== */
#edn-mark-warleague a,
#edn-mark-hanstudios a,
#edn-credit a {
  color: inherit;
  text-decoration: none;
  transition: color 200ms var(--ease-out), opacity 200ms var(--ease-out);
}
#edn-mark-warleague a:hover,
#edn-mark-hanstudios a:hover,
#edn-credit a:hover,
#edn-mark-warleague a:focus-visible,
#edn-mark-hanstudios a:focus-visible,
#edn-credit a:focus-visible { color: var(--eva); }
/* The logo is an image, so it answers by lifting rather than by colour. */
#edn-mark-warleague a:hover img,
#edn-mark-hanstudios a:hover img { opacity: .82; }
#edn-mark-warleague a:focus-visible,
#edn-mark-hanstudios a:focus-visible,
#edn-credit a:focus-visible { outline: 2px solid var(--eva); outline-offset: 3px; }
/* The credit reads as a link without relying on colour alone. */
#edn-credit a { text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: #a4b0a655; }
#edn-credit a:hover { text-decoration-color: currentColor; }
