/* Shared case-study components and responsive layout. */
.layers {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 24px 0;
}
.layer {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 18px;
  background: var(--bg-raised);
}
.layer .lhead {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}
.layer .lnum {
  font-family: ui-monospace, monospace;
  font-size: 12px;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 1px 7px;
}
.layer h3 {
  font-size: 15.5px;
  margin: 0;
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.chip {
  font-size: 12.5px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px;
  color: var(--text-body);
}
.layer-arrow {
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  margin: -2px 0;
}
.platform-table {
  width: 100%;
  border-collapse: collapse;
  margin: 24px 0;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  font-size: 13px;
}
.platform-table caption {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.platform-table th,
.platform-table td {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}
.platform-table thead th {
  color: var(--text);
  background: var(--bg);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.platform-table tbody tr:last-child th,
.platform-table tbody tr:last-child td {
  border-bottom: 0;
}
.platform-table tbody th {
  width: 24%;
  color: var(--text);
  font-size: 14px;
  line-height: 1.45;
}
.platform-table tbody td:nth-child(2) {
  width: 27%;
  color: var(--text-body);
}
.platform-table tbody td:last-child {
  color: var(--text-muted);
  line-height: 1.65;
}
.table-num {
  display: inline-block;
  margin-right: 8px;
  color: var(--accent);
  font: 12px ui-monospace, monospace;
}
/* Case studies: "On this page" contents in a sticky column beside the
   sections on wide screens. Narrower screens show the sections alone. */
.cs-toc {
  display: none;
}
@media (min-width: 1100px) {
  .cs-body.has-toc {
    max-width: var(--maxw);
    margin: 0 auto;
    padding: 0 32px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 200px;
    gap: 56px;
    align-items: start;
  }
  /* The sections keep their own .wrap; inside the grid it must not add a
     second width limit or side padding. */
  .cs-body.has-toc .cs-main .wrap {
    max-width: none;
    padding: 0;
  }
  .cs-toc {
    display: block;
    position: sticky;
    top: 96px;
    padding: 48px 0;
    max-height: calc(100vh - 110px);
    overflow-y: auto;
  }
}
.cs-toc-title {
  font: 600 11px/1.6 ui-monospace, monospace;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.cs-toc ol {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--border);
}
.cs-toc a {
  display: block;
  padding: 5px 0 5px 14px;
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-muted);
  text-decoration: none;
}
.cs-toc a:hover,
.cs-toc a.is-active {
  color: var(--accent);
  border-left-color: var(--accent);
}
.hubwrap {
  margin: 28px 0;
  /* The SVG scales with its box; on wide pages keep it at reading width so
     its labels stay close to the size they were drawn at. */
  max-width: var(--measure, 860px);
}
.hub-svg {
  width: 100%;
  height: auto;
}
.hub-node rect {
  fill: var(--bg-raised);
  stroke: var(--border);
  stroke-width: 1.5;
  transition:
    stroke 0.2s ease,
    fill 0.2s ease;
}
.hub-node.center rect {
  fill: var(--inverse-bg);
  stroke: var(--accent);
}
.hub-node text {
  font-family: system-ui, sans-serif;
  font-size: 11.5px;
  fill: var(--text);
  transition: fill 0.2s ease;
}
.hub-node.center text {
  fill: var(--inverse-heading);
}
.hub-node.active rect {
  stroke: var(--accent);
  stroke-width: 2.5;
  fill: var(--accent-soft);
}
.hub-node.active text {
  fill: var(--text);
}
.hub-node.danger rect {
  stroke-dasharray: 4, 3;
}
.hub-line {
  stroke: var(--line);
  stroke-width: 1.5;
  fill: none;
  transition:
    stroke 0.2s ease,
    stroke-width 0.2s ease;
}
.hub-line.active {
  stroke: var(--accent);
  stroke-width: 2.5;
}
.hub-pulse {
  fill: var(--accent-bright);
  opacity: 0;
}
.hub-caption {
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 8px;
  min-height: 60px;
}
.diagram-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  flex-wrap: wrap;
  gap: 12px;
}
.diagram-top h3 {
  font-size: 15.5px;
}
/* Notes under a hub diagram (classes, not inline styles: the CSP allows no inline CSS). */
.hub-note,
.hub-detail {
  color: var(--text-muted);
}
.hub-note {
  font-size: 13.5px;
  margin-top: 10px;
}
.hub-detail {
  font-size: 14px;
  margin-top: 14px;
}
#failoverPlayBtn,
#tgwPlayBtn,
#cachePlayBtn {
  font-family: system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid var(--accent);
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  min-height: 44px;
}
#failoverPlayBtn:hover,
#tgwPlayBtn:hover,
#cachePlayBtn:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
#failoverPlayBtn:focus-visible,
#tgwPlayBtn:focus-visible,
#cachePlayBtn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.gtable {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
  font-size: 13.5px;
  min-width: 580px;
}
.gtable th {
  text-align: left;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}
.gtable td {
  padding: 12px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.gtable .w-18 { width: 18%; }
.gtable .w-20 { width: 20%; }
.gtable .w-30 { width: 30%; }
.gtable .w-32 { width: 32%; }
.gtable tr:last-child td {
  border-bottom: none;
}
.gtable .gnum {
  font-family: ui-monospace, monospace;
  color: var(--accent);
  font-weight: 600;
}
pre.code {
  background: var(--inverse-bg);
  color: var(--inverse-text);
  border-radius: 12px;
  padding: 16px 18px;
  overflow-x: auto;
  font-family: ui-monospace, monospace;
  font-size: 12.5px;
  line-height: 1.6;
  margin: 18px 0;
}
.seq {
  counter-reset: step;
  margin: 20px 0;
}
.seq-item {
  position: relative;
  padding: 0 0 22px 34px;
  border-left: 2px solid var(--border);
}
.seq-item:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}
.seq-item::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: -13px;
  top: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--inverse-bg);
  color: var(--accent-bright);
  font-family: ui-monospace, monospace;
  font-size: 11.5px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.seq-item h3 {
  font-size: 14.5px;
  margin-bottom: 4px;
}
.seq-item p {
  font-size: 14px;
  margin-bottom: 0;
  color: var(--text-muted);
}
.outcomes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
  margin: 22px 0;
}
.outcome {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
  background: var(--bg-raised);
}
.outcome .num {
  font-family: inherit;
  font-size: 26px;
  font-weight: 700;
  color: var(--accent2);
}
.outcome .txt {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 4px;
}
.hub-line.public {
  stroke-dasharray: 4, 4;
  stroke: var(--text-muted);
}
.hub-line.public.active {
  stroke: var(--accent);
  stroke-dasharray: 4, 4;
}
.hub-node.public rect {
  stroke-dasharray: 4, 3;
}
.hub-legend {
  display: flex;
  gap: 18px;
  justify-content: center;
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 14px;
}
.hub-groupbox {
  fill: none;
  stroke: var(--line);
  stroke-width: 1.5;
  stroke-dasharray: 3, 4;
}
/* A label on a connector (e.g. the public entry path). */
.hub-edge-label {
  font-family: system-ui, sans-serif;
  font-size: 10.5px;
  fill: var(--text-muted);
}
.hub-group-label {
  font-family: system-ui, sans-serif;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  fill: var(--text-muted);
  text-anchor: middle;
}
.lg-dot {
  display: inline-block;
  width: 16px;
  height: 0;
  border-top: 2px solid var(--text-muted);
  vertical-align: middle;
  margin-right: 5px;
}
.lg-public {
  border-top-style: dashed;
}
.lg-internal {
  border-top-style: solid;
}
/* Reading pages share the homepage width (--maxw from site.css), so the
   logo, breadcrumb, title, and content line up on every page. Running text
   keeps a comfortable line length (--measure); figures, tables, cards, and
   diagrams use the full width. */
.deepdive {
  --measure: 860px;
}
.deepdive main :is(p, ul:not([class]), ol:not([class]), dl, blockquote, h2, h3, h4, .callout) {
  max-width: var(--measure);
}
.deepdive .topnav .wrap {
  max-width: var(--site-maxw);
}
.deepdive .back {
  font-size: 13px;
  text-decoration: none;
}
.deepdive .hero {
  padding: 36px 0 48px;
  border-bottom: 1px solid var(--border);
}
.deepdive .hero h1 {
  font-size: clamp(34px, 4.5vw, 52px);
  max-width: 800px;
  line-height: 1.12;
  margin: 16px 0 22px;
  letter-spacing: -0.045em;
}
.deepdive .hero .sub {
  max-width: 760px;
  font-size: 15px;
}
.deepdive .meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px 36px;
  margin-top: 32px;
  font-size: 12px;
  color: var(--text-muted);
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.deepdive .meta b {
  color: var(--text);
}
.deepdive section {
  padding: 48px 0;
}
.deepdive h2 {
  font-size: 28px;
  margin: 12px 0 22px;
  font-weight: 550;
  line-height: 1.25;
}
.deepdive h3 {
  letter-spacing: -0.015em;
}
.deepdive p {
  margin-bottom: 16px;
}
.deepdive li {
  margin-bottom: 10px;
}
.deepdive b {
  color: var(--text);
}
.deepdive code {
  font:
    0.9em ui-monospace,
    monospace;
  overflow-wrap: anywhere;
}
.deepdive .callout {
  border-left: 2px solid var(--accent);
  background: var(--bg-raised);
  padding: 20px 24px;
  font-size: 14px;
  margin: 24px 0;
}
.deepdive .closing .wrap {
  display: block;
  text-align: left;
}
.deepdive .closing {
  padding: 48px 0;
}
.deepdive .closing h2 {
  max-width: 700px;
}
.deepdive .cta {
  display: inline-block;
  background: var(--accent);
  color: var(--bg);
  border-radius: 4px;
  padding: 12px 20px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}
.next-study {
  padding-top: 32px;
  padding-bottom: 32px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.next-study a {
  color: var(--accent);
  font-size: 13px;
}
.table-scroll,
.diagram-scroll {
  max-width: 100%;
  overflow-x: auto;
}
.diagram-scroll .hub-svg {
  display: block;
  min-width: 620px;
}
.layer .chip {
  overflow-wrap: anywhere;
  max-width: 100%;
}
.deepdive pre.code {
  max-width: 100%;
}
/* "Key results" strip directly under a case-study hero */
.deepdive section.key-results {
  padding-top: 8px;
  padding-bottom: 36px;
}
.deepdive .key-results h2.section-eyebrow {
  font: 600 11px/1.6 ui-monospace, monospace;
  letter-spacing: 0.14em;
  margin: 0;
}
.key-results .outcomes {
  margin: 14px 0 0;
}
/* Markdown pipe tables (scripts/lib/markdown.mjs) */
.table-wrap {
  max-width: 100%;
  overflow-x: auto;
  margin: 22px 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-raised);
}
.md-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
  line-height: 1.55;
}
.md-table th,
.md-table td {
  padding: 12px 16px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
}
.md-table .align-center { text-align: center; }
.md-table .align-right { text-align: right; }
.md-table thead th {
  background: var(--bg);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.md-table tbody td:first-child {
  color: var(--text);
  font-weight: 600;
}
.md-table tbody tr:last-child td {
  border-bottom: 0;
}
/* Wide ASCII diagrams: keep the monospace layout, but tell phone readers
   the block scrolls rather than letting the right side vanish silently. */
.wide-block {
  margin: 18px 0;
}
.wide-block pre.code {
  margin: 0;
}
.scroll-hint {
  display: none;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-muted);
}
.deepdive .seq {
  padding-left: 12px;
}
.case-study-links {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-top: 24px;
}
.case-study-links a {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 22px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
  transition: border-color 0.2s, transform 0.2s ease, box-shadow 0.2s ease;
}
.case-study-links a:hover {
  border-color: var(--accent);
}
@media (hover: hover) {
  .case-study-links a:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
  }
}
.case-study-links span {
  font-size: 11px;
  color: var(--accent);
}
.case-study-links strong {
  color: var(--text);
  line-height: 1.4;
}
.case-study-links small {
  color: var(--text-muted);
  font-size: 12px;
}
.problem-solution {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
}
.problem-solution h3 {
  font-size: 17px;
  margin-bottom: 12px;
}
.problem-solution p {
  font-size: 14px;
}
.implementation-notes {
  font-size: 14px;
}
.implementation-notes summary {
  cursor: pointer;
  color: var(--accent);
  /* WCAG 2.2 target size: at least 24px tall to tap. */
  padding: 6px 0;
}
.implementation-notes ul {
  margin-top: 18px;
}
@media (max-width: 640px) {
  .case-study-links,
  .problem-solution {
    grid-template-columns: 1fr;
  }
  .deepdive .hero {
    padding: 40px 0 32px;
  }
  .deepdive .meta {
    grid-template-columns: 1fr;
  }
  .deepdive h2 {
    font-size: 25px;
  }
  .deepdive section {
    padding: 36px 0;
  }
  .outcomes {
    grid-template-columns: 1fr;
  }
  .scroll-hint {
    display: block;
  }
  /* 12.5px keeps commands readable on a phone (Lighthouse's legibility
     floor is 12px); long lines still scroll sideways. */
  .deepdive pre.code {
    font-size: 12.5px;
  }
  /* Tables become stacked label/value cards instead of a squeezed grid. */
  .table-wrap {
    border: 0;
    background: transparent;
    overflow: visible;
  }
  .md-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .md-table,
  .md-table tbody,
  .md-table tr,
  .md-table td {
    display: block;
    width: 100%;
  }
  .md-table tr {
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--bg-raised);
    padding: 6px 0;
    margin-bottom: 12px;
  }
  .md-table td {
    border-bottom: 0;
    padding: 6px 16px;
  }
  .md-table td::before {
    content: attr(data-label);
    display: block;
    font-size: 10.5px;
    font-weight: 650;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 2px;
  }
  .md-table tbody tr:last-child td {
    border-bottom: 0;
  }
  .deepdive .diagram-top {
    align-items: flex-start;
  }
  .deepdive .hub-caption {
    text-align: left;
  }
}

/* ---------------------------------- Header motifs (scripts/lib/motifs.mjs)
   A small animated illustration beside the title of each case study and
   playbook (below the summary on narrower screens, where the title needs the
   full width). Decorative only. Packets move by SVG animation, so reduced
   motion hides them; the CSS cycles below are stopped by the site-wide
   reduced-motion rule. */
.hero-split {
  display: block;
}
.motif {
  display: block;
  width: 100%;
  max-width: 280px;
  height: auto;
  margin-top: 28px;
}
@media (min-width: 1100px) {
  .hero-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 48px;
    align-items: center;
  }
  .motif {
    width: 240px;
    margin-top: 0;
  }
}
/* Phones: the illustration sits under the summary and only pushes the
   content down, so it's left out there. */
@media (max-width: 640px) {
  .motif {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .motif .m-packets {
    display: none;
  }
}
.motif text {
  fill: var(--text-muted);
  font: 600 8px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.1em;
  text-anchor: middle;
}
.motif .m-start { text-anchor: start; }
.motif .m-end { text-anchor: end; }
.motif .m-big { font-size: 18px; }
.motif .m-hot { fill: var(--accent); }
.motif .m-warn { fill: var(--accent2); }
.motif .m-muted { fill: var(--text-muted); opacity: 0.8; }
.motif .m-line,
.motif .m-grid,
.motif .m-row {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.2;
}
.motif .m-dash {
  stroke: var(--accent);
  stroke-dasharray: 3 5;
  animation: m-flow 1s linear infinite;
}
.motif .m-node {
  fill: var(--bg);
  stroke: var(--border);
  stroke-width: 1.2;
}
.motif .m-hub { stroke: var(--accent); }
.motif .m-dashed { stroke-dasharray: 4 3; }
.motif .m-pk { fill: var(--accent); }
.motif .m-pk-plain { fill: var(--text-muted); }
@keyframes m-flow {
  to { stroke-dashoffset: -8; }
}

/* failover: every 10s the primary fails and DNS shifts traffic to the secondary. */
.motif-failover .mf-primary { animation: mf-primary 10s infinite; }
.motif-failover .mf-standby { stroke-dasharray: 4 3; animation: mf-standby 10s infinite; }
.motif-failover .mf-link-p { animation: mf-link-p 10s infinite; }
.motif-failover .mf-link-s { stroke-dasharray: 3 4; animation: mf-link-s 10s infinite; }
.motif-failover .mf-to-p,
.motif-failover .mf-ok { animation: m-normal 10s infinite; }
.motif-failover .mf-to-s,
.motif-failover .mf-bad { opacity: 0; animation: m-failover 10s infinite; }
.motif-failover .m-state:not(.m-warn):not(.m-muted) { fill: var(--accent); }
@keyframes m-normal {
  0%, 45% { opacity: 1; }
  50%, 85% { opacity: 0; }
  90%, 100% { opacity: 1; }
}
@keyframes m-failover {
  0%, 45% { opacity: 0; }
  50%, 85% { opacity: 1; }
  90%, 100% { opacity: 0; }
}
@keyframes mf-primary {
  0%, 45%, 90%, 100% { stroke: var(--border); }
  50%, 85% { stroke: var(--accent2); }
}
@keyframes mf-standby {
  0%, 45%, 90%, 100% { stroke: var(--border); stroke-dasharray: 4 3; }
  50%, 85% { stroke: var(--accent); stroke-dasharray: none; }
}
@keyframes mf-link-p {
  0%, 45%, 90%, 100% { stroke: var(--border); stroke-dasharray: none; }
  50%, 85% { stroke: var(--accent2); stroke-dasharray: 2 4; }
}
@keyframes mf-link-s {
  0%, 45%, 90%, 100% { stroke: var(--border); stroke-dasharray: 3 4; }
  50%, 85% { stroke: var(--accent); stroke-dasharray: none; }
}

/* pipeline: stages pass one by one, the bar fills, the release goes live. */
.motif-pipeline .mp-s1 { animation: mp-s1 7s infinite; }
.motif-pipeline .mp-s2 { animation: mp-s2 7s infinite; }
.motif-pipeline .mp-s3 { animation: mp-s3 7s infinite; }
.motif-pipeline .mp-s4 { animation: mp-s4 7s infinite; }
.motif-pipeline .m-track { fill: var(--border); }
.motif-pipeline .m-bar {
  fill: var(--accent);
  transform-box: fill-box;
  transform-origin: left center;
  animation: mp-bar 7s infinite;
}
.motif-pipeline .mp-done { fill: var(--accent); opacity: 0; animation: mp-done 7s infinite; }
@keyframes mp-s1 { 0%, 2% { stroke: var(--border); fill: var(--bg); } 6%, 88% { stroke: var(--accent); fill: var(--accent-soft); } 94%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mp-s2 { 0%, 20% { stroke: var(--border); fill: var(--bg); } 24%, 88% { stroke: var(--accent); fill: var(--accent-soft); } 94%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mp-s3 { 0%, 38% { stroke: var(--border); fill: var(--bg); } 42%, 88% { stroke: var(--accent); fill: var(--accent-soft); } 94%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mp-s4 { 0%, 56% { stroke: var(--border); fill: var(--bg); } 60%, 88% { stroke: var(--accent); fill: var(--accent-soft); } 94%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mp-bar { 0% { transform: scaleX(0); } 62%, 88% { transform: scaleX(1); } 94%, 100% { transform: scaleX(0); } }
@keyframes mp-done { 0%, 62% { opacity: 0; } 66%, 88% { opacity: 1; } 94%, 100% { opacity: 0; } }

/* replication: replica rows catch up in turn. */
.motif-replication .m-row { stroke: var(--accent); opacity: 0.25; }
.motif-replication .mr-1 { animation: mr-row 3s infinite; }
.motif-replication .mr-2 { animation: mr-row 3s 1s infinite; }
.motif-replication .mr-3 { animation: mr-row 3s 2s infinite; }
@keyframes mr-row { 0%, 100% { opacity: 0.25; } 15%, 40% { opacity: 1; } }

/* migration: servers drain from on-prem and land in AWS, wave by wave. */
.motif-migration .mm-src1 { animation: mm-src1 9s infinite; }
.motif-migration .mm-src2 { animation: mm-src2 9s infinite; }
.motif-migration .mm-src3 { animation: mm-src3 9s infinite; }
.motif-migration .mm-dst1 { animation: mm-dst1 9s infinite; }
.motif-migration .mm-dst2 { animation: mm-dst2 9s infinite; }
.motif-migration .mm-dst3 { animation: mm-dst3 9s infinite; }
@keyframes mm-src1 { 0%, 8% { opacity: 1; } 14%, 90% { opacity: 0.25; } 96%, 100% { opacity: 1; } }
@keyframes mm-src2 { 0%, 34% { opacity: 1; } 40%, 90% { opacity: 0.25; } 96%, 100% { opacity: 1; } }
@keyframes mm-src3 { 0%, 60% { opacity: 1; } 66%, 90% { opacity: 0.25; } 96%, 100% { opacity: 1; } }
@keyframes mm-dst1 { 0%, 16% { stroke: var(--border); fill: var(--bg); } 22%, 90% { stroke: var(--accent); fill: var(--accent-soft); } 96%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mm-dst2 { 0%, 42% { stroke: var(--border); fill: var(--bg); } 48%, 90% { stroke: var(--accent); fill: var(--accent-soft); } 96%, 100% { stroke: var(--border); fill: var(--bg); } }
@keyframes mm-dst3 { 0%, 68% { stroke: var(--border); fill: var(--bg); } 74%, 90% { stroke: var(--accent); fill: var(--accent-soft); } 96%, 100% { stroke: var(--border); fill: var(--bg); } }

/* stream: messages fill and drain the queue. */
.motif-stream .m-cell { fill: var(--accent); opacity: 0.15; animation: ms-cell 2.5s infinite; }
.motif-stream .ms-c2 { animation-delay: 0.3s; }
.motif-stream .ms-c3 { animation-delay: 0.6s; }
.motif-stream .ms-c4 { animation-delay: 0.9s; }
.motif-stream .ms-c5 { animation-delay: 1.2s; }
@keyframes ms-cell { 0%, 100% { opacity: 0.15; } 30%, 50% { opacity: 0.8; } }

/* monitor: the latency trace draws, breaches the SLO, alerts, then resolves. */
.motif-monitor .m-grid { opacity: 0.5; }
.motif-monitor .m-slo { fill: none; stroke: var(--accent2); stroke-width: 1; stroke-dasharray: 4 4; opacity: 0.7; }
.motif-monitor .m-trace {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  animation: mo-trace 8s infinite;
}
.motif-monitor .m-badge { fill: var(--accent-soft); stroke: var(--accent); }
.motif-monitor .m-badge-warn { fill: var(--bg); stroke: var(--accent2); }
.motif-monitor .mo-alert { opacity: 0; animation: mo-alert 8s infinite; }
.motif-monitor .mo-ok { opacity: 0; animation: mo-ok 8s infinite; }
@keyframes mo-trace { 0% { stroke-dashoffset: 100; opacity: 1; } 50%, 92% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes mo-alert { 0%, 32% { opacity: 0; } 36%, 60% { opacity: 1; } 64%, 100% { opacity: 0; } }
@keyframes mo-ok { 0%, 62% { opacity: 0; } 66%, 90% { opacity: 1; } 95%, 100% { opacity: 0; } }

/* security: data passes through the KMS lock while the key ring rotates. */
.motif-security .m-ring {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.2;
  stroke-dasharray: 6 8;
  opacity: 0.6;
  transform-box: view-box;
  transform-origin: 120px 90px;
  animation: msec-ring 12s linear infinite;
}
.motif-security .m-keyhole { fill: var(--accent); }
.motif-security .m-shackle { fill: none; }
@keyframes msec-ring { to { transform: rotate(360deg); } }

/* Flow diagrams (```flow fences, scripts/lib/markdown.mjs): boxes joined by
   labelled arrows, read top to bottom. Pure CSS, so they work without
   JavaScript and follow the light/dark theme tokens. */
.deepdive .flow {
  margin: 28px 0;
  padding: 22px 20px 20px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
}
.deepdive .flow-title {
  font: 11px ui-monospace, monospace;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 16px;
}
.deepdive .flow-body {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  max-width: 620px;
  margin: 0 auto;
}
.deepdive .flow-node {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  text-align: center;
}
.deepdive .flow-node strong {
  display: block;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
}
.deepdive .flow-node span {
  display: block;
  color: var(--text-muted);
  font-size: 12.5px;
  margin-top: 2px;
}
.deepdive .flow-node.is-key {
  border-color: var(--accent);
  background: var(--accent-soft);
}
/* Arrow pinned to the centre line; its label sits to the right. */
.deepdive .flow-edge {
  display: grid;
  grid-template-columns: 1fr 2px 1fr;
  align-items: center;
  column-gap: 10px;
  min-height: 38px;
  padding: 4px 0;
}
.deepdive .flow-arrow {
  position: relative;
  grid-column: 2;
  width: 2px;
  align-self: stretch;
  min-height: 30px;
  background: var(--accent);
}
.deepdive .flow-arrow::after {
  content: "";
  position: absolute;
  left: -4px;
  bottom: -1px;
  border: 5px solid transparent;
  border-top: 7px solid var(--accent);
  border-bottom: 0;
}
.deepdive .flow-edge-label {
  grid-column: 3;
  font-size: 12px;
  color: var(--text-body);
}
.deepdive .flow-group {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px dashed var(--text-muted);
  border-radius: 10px;
  padding: 26px 12px 12px;
  margin: 2px 0;
}
.deepdive .flow-group-label,
.deepdive .flow-path-label {
  position: absolute;
  top: 7px;
  left: 12px;
  font: 10.5px ui-monospace, monospace;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.deepdive .flow-paths {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 12px;
}
.deepdive .flow-path {
  position: relative;
  display: flex;
  flex-direction: column;
  border-top: 2px solid var(--accent);
  padding-top: 26px;
}
.deepdive .flow-loop {
  margin-top: 12px;
  text-align: center;
  font-size: 12.5px;
  color: var(--accent);
}
@media (max-width: 640px) {
  .deepdive .flow-paths {
    grid-auto-flow: row;
  }
  .deepdive .flow {
    padding: 18px 12px 14px;
  }
}

/* "See it in practice" / "Learn the concepts" cross-links between
   learning-path modules and case studies. */
.deepdive .related-links {
  margin: 48px 0 8px;
}
.deepdive .related-links h2 {
  font-size: 18px;
  margin-bottom: 14px;
}
.deepdive .related-links ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
}
.deepdive .related-links a {
  display: flex;
  flex-direction: column;
  gap: 4px;
  height: 100%;
  padding: 16px 18px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
}
.deepdive .related-links a:hover,
.deepdive .related-links a:focus-visible {
  border-color: var(--accent);
}
.deepdive .related-eyebrow {
  font: 10.5px ui-monospace, monospace;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.deepdive .related-links strong {
  color: var(--text);
  font-size: 14.5px;
}
.deepdive .related-links small {
  color: var(--text-muted);
  font-size: 13px;
}

/* Traffic walkthrough (assets/flow-player.js): Play / Back / Next move a
   highlight through the diagram, one hop at a time. */
.deepdive .flow-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: -4px 0 16px;
}
.deepdive .flow-btn {
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  padding: 8px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-raised);
  color: var(--text);
  cursor: pointer;
}
.deepdive .flow-btn:hover:not(:disabled) {
  border-color: var(--accent);
}
.deepdive .flow-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.deepdive .flow-btn:disabled {
  opacity: 0.5;
  cursor: default;
}
.deepdive .flow-play {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
.deepdive .flow-caption {
  margin: 16px auto 0;
  max-width: 620px;
  padding: 12px 14px;
  border-left: 2px solid var(--accent);
  background: var(--bg-raised);
  font-size: 13.5px;
  color: var(--text-body);
  min-height: 3.2em;
}
.deepdive .flow-caption strong {
  display: block;
  color: var(--text);
}
.deepdive .flow-caption span {
  display: block;
  margin-top: 4px;
}
.deepdive .flow-caption .flow-caption-where {
  font: 10.5px ui-monospace, monospace;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.deepdive .flow .flow-node,
.deepdive .flow .flow-edge {
  transition: opacity 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.deepdive .flow.is-walking .flow-node,
.deepdive .flow.is-walking .flow-edge {
  opacity: 0.4;
}
.deepdive .flow.is-walking .is-visited {
  opacity: 0.85;
}
.deepdive .flow.is-walking .flow-node.is-active,
.deepdive .flow.is-walking .flow-edge.is-active {
  opacity: 1;
}
.deepdive .flow.is-walking .flow-node.is-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), 0 0 18px var(--accent-soft);
}
.deepdive .flow-edge.is-active .flow-edge-label {
  color: var(--text);
  font-weight: 600;
}
/* The "packet": a dot that runs down the active arrow. */
.deepdive .flow-edge.is-active .flow-arrow::before {
  content: "";
  position: absolute;
  left: -4px;
  top: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent);
  animation: flow-packet 1.1s ease-in infinite;
}
@keyframes flow-packet {
  from { top: -4px; opacity: 0; }
  20% { opacity: 1; }
  to { top: calc(100% - 8px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .deepdive .flow-edge.is-active .flow-arrow::before {
    animation: none;
    top: calc(50% - 5px);
  }
}
.motion-paused .deepdive .flow-edge.is-active .flow-arrow::before {
  animation: none;
  top: calc(50% - 5px);
}
