/* Layout and components. Values come from tokens.css only. */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-padding-top: 136px; }
@media (max-width: 759.98px) { html { scroll-padding-top: 72px; } }

body {
  font-synthesis: none;
  margin: 0;
  background: var(--paper);
  color: var(--navy);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
  overflow-x: clip;
}

img { max-width: 100%; height: auto; display: block; }

h1, h2 {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--navy);
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); line-height: 1.1; letter-spacing: -0.01em; }
h2 { font-size: var(--fs-h2); line-height: 1.2; }
h3 {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.3;
  margin: 0;
}
p { margin: 0; }
b, strong { font-weight: 600; }

a {
  color: var(--blue);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  transition: color var(--ease), opacity var(--ease);
}
a:hover { opacity: 0.85; }

:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  background: var(--paper);
  padding: var(--s-8) var(--s-16);
  z-index: 10;
}
.skip:focus { top: var(--s-8); }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.reading { max-width: var(--reading); }

.section { padding-block: var(--section-pad); }
.section + .section { border-top: 1px solid var(--line); }
.section--surface { background: var(--surface); }
.section > .container > * + * { margin-top: var(--s-24); }

.lede { color: var(--navy); max-width: var(--reading); }
.muted, .caption { color: var(--ink-muted); }
.caption { font-size: var(--fs-small); line-height: 1.5; max-width: var(--reading); }
.label {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Samples: everything still to be supplied by the owner carries this badge. */
.sample-badge {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--fs-note);
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1;
  padding: 4px 6px;
  border: 1.5px dashed var(--error);
  border-radius: 4px;
  color: var(--error);
  vertical-align: middle;
  margin-inline: 4px;
  white-space: nowrap;
}
mark.todo {
  background: transparent;
  color: var(--error);
  font-weight: 600;
  border-bottom: 1.5px dashed var(--error);
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 14px 24px;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  border: 1.5px solid transparent;
  transition: background-color var(--ease), color var(--ease), opacity var(--ease);
}
.btn:hover { opacity: 1; }
.btn--primary { background: var(--blue); color: var(--paper); border-color: var(--blue); }
.btn--primary:hover,
.btn--primary:active { background: color-mix(in srgb, var(--blue) 80%, var(--navy)); border-color: color-mix(in srgb, var(--blue) 80%, var(--navy)); }
.btn--secondary { background: transparent; color: var(--blue); border-color: var(--blue); }
.btn--secondary:hover { background: var(--blue-tint); }
.btn[disabled],
.btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.btns { display: flex; flex-wrap: wrap; gap: var(--s-16); }

/* Header */
.site-header { position: sticky; top: 0; z-index: 20; border-bottom: 1px solid var(--line); background: var(--paper); }
.site-header .container { display: flex; justify-content: center; padding-block: var(--s-16); }
/* Logo on top, menu tucked underneath at exactly the logo's width: the nav takes no width of its own. */
.masthead { display: grid; gap: var(--s-4); width: max-content; max-width: 100%; justify-items: stretch; }
.site-nav { width: 0; min-width: 100%; }
.brand { display: flex; align-items: center; justify-content: center; text-decoration: none; color: var(--navy); }
.brand img { height: 36px; width: auto; }
.brand .brand-mark { display: none; }
.brand .wordmark {
  display: none;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1;
  color: var(--navy);
}
/* Dark is the default theme: the dark logo (site/img/logo-dark.svg) shows unless the visitor chose light. */
:root:not([data-theme="light"]) .logo-l, :root[data-theme="light"] .logo-d { display: none; }
@media (min-width: 900px) { .brand img { height: 38px; } }
.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-24);
}
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--navy);
  text-decoration: none;
}
.site-nav a:hover { text-decoration: underline; }
.site-nav a[aria-current="page"] { text-decoration: underline; }

/* Hero */
.hero { padding-block: var(--section-pad); }
.hero-title { width: fit-content; max-width: 100%; }
.hero-title .l1 { display: block; font-size: clamp(40px, 5.6vw, 72px); line-height: 1.05; text-wrap: balance; }
.hero .second { font-size: var(--fs-h3); font-weight: 400; line-height: 1.4; max-width: 34ch; margin-top: var(--s-32); text-wrap: balance; }
.hero .descriptor { color: var(--ink-muted); margin-top: var(--s-16); max-width: var(--reading); }
.hero .btns { margin-top: var(--s-32); }

/* Pattern transfer */
.units {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: var(--s-16);
}
.units li {
  background: var(--surface);
  /* Same border as the Unit method wheel's explanation box: 1.5px, purple for the solid units. */
  border: 1.5px solid var(--prove);
  border-radius: var(--radius);
  padding: var(--s-16) var(--s-24) var(--s-24);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
/* The next units are still open: a dotted grey border, like the wheel's "we monitor" state. */
.units li.open { border-style: dotted; border-color: var(--handoff); }
.units b { font-family: var(--font-head); font-size: var(--fs-h3); font-weight: 600; line-height: 1.3; }
.units span { color: var(--ink-muted); font-size: var(--fs-small); }

/* Practice cards */
.cards {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-24);
}
@media (min-width: 760px) {
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card--wide { grid-column: 1 / -1; }
  .card--wide dl { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-24); }
}
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 4px solid var(--card-colour, var(--line));
  border-radius: var(--radius);
  padding: var(--s-24);
  display: flex;
  flex-direction: column;
  gap: var(--s-16);
  min-width: 0;
}
.card--deals { --card-colour: var(--deals); }
.card--insights { --card-colour: var(--insights); }
.card--delivery { --card-colour: var(--delivery); }
.card .card-label {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--card-colour);
}
.card h3 { font-size: var(--fs-body); }
.card dl { margin: 0; display: grid; gap: var(--s-16); }
.card dt { font-size: var(--fs-label); font-weight: 600; color: var(--ink-muted); }
.card dd { margin: var(--s-4) 0 0; }
.card .btns { margin-top: auto; padding-top: var(--s-8); }

/* Figures and diagrams. Sizes come from the diagram tokens in tokens.css. */
figure { margin: 0; }
figure > * + * { margin-top: var(--s-16); }
.plain-line { font-family: var(--font-head); font-weight: 600; font-size: var(--fs-h3); line-height: 1.3; max-width: var(--reading); }

.section > .container > figure.diagram-figure,
.section > .container > .wheelbox { margin-block: var(--diagram-space); }
.section > .container > figure.diagram-figure:last-child,
.section > .container > .wheelbox:last-child { margin-bottom: 0; }
.diagram-figure,
.wheelbox { max-width: var(--diagram-max-width); }
.scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  -webkit-overflow-scrolling: touch;
}
.section--surface .scroll { background: var(--paper); }
.diagram { display: block; width: 100%; min-width: var(--diagram-min-width); height: auto; color: var(--navy); }
.swipe-hint { font-size: var(--fs-note); color: var(--ink-muted); }
.swipe-hint::after { content: " \2192"; }
@media (min-width: 900px) {
  /* Frames run out to the container edge (1120px), past the side padding, so diagrams are as large as the page allows. */
  .diagram-figure,
  .wheelbox { margin-inline: calc(var(--gutter) * -1); }
  .diagram-figure .scroll { border-inline: 0; border-radius: 0; overflow-x: visible; }
  .diagram-figure figcaption { padding-inline: var(--gutter); }
  .swipe-hint { display: none; }
}
@media (min-width: 1120px) {
  .diagram-figure .scroll { border: 1px solid var(--line); border-radius: var(--radius); }
}

.diagram text { font-family: var(--font-body); }
.d-h { font-size: var(--diagram-size-heading); font-weight: 600; fill: var(--navy); }
.d-t { font-size: var(--diagram-size-label); fill: var(--navy); }
.d-num { font-size: var(--diagram-size-label); font-weight: 600; fill: var(--navy); }
.d-n { font-size: var(--diagram-size-note); fill: var(--ink-muted); }
.d-k { font-size: var(--diagram-size-note); font-weight: 600; letter-spacing: 0.08em; fill: var(--ink-muted); }
.d-ph { font-size: var(--diagram-size-note); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; fill: var(--ink-muted); }
.d-chip { font-size: var(--diagram-size-note); font-weight: 600; fill: var(--navy); }
.d-tag { font-size: var(--diagram-size-note); font-weight: 600; fill: var(--loop); }
.d-hand { font-size: var(--diagram-size-note); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; fill: var(--prove); }
.d-strong { font-weight: 600; }
.d-node { fill: var(--paper); stroke: var(--line); stroke-width: 1.5; }
.d-node.insights { stroke: var(--insights); stroke-width: 2.5; fill: color-mix(in srgb, var(--insights) 12%, var(--paper)); }
.d-node.deals { stroke: var(--deals); stroke-width: 2.5; fill: color-mix(in srgb, var(--deals) 10%, var(--paper)); }
.d-node.delivery { stroke: var(--delivery); stroke-width: 2.5; fill: color-mix(in srgb, var(--delivery) 10%, var(--paper)); }
.d-node.om { stroke: var(--operating-border); stroke-width: 2.5; fill: var(--operating); }
.d-node.lead { stroke: var(--prove); stroke-width: 2.5; fill: color-mix(in srgb, var(--prove) 6%, var(--paper)); }
.d-node.zoom { stroke: var(--prove); stroke-width: 2.5; fill: color-mix(in srgb, var(--prove) 16%, var(--paper)); }
.d-node.mon { stroke: var(--handoff); stroke-width: 1.5; stroke-dasharray: 5 4; fill: var(--paper); }
.d-bud { fill: color-mix(in srgb, var(--loop) 12%, var(--paper)); }
.d-bud.deals { fill: color-mix(in srgb, var(--deals) 14%, var(--paper)); }
.d-bud.delivery { fill: color-mix(in srgb, var(--delivery) 14%, var(--paper)); }
.d-bud.neutral { fill: var(--surface); }
.d-flow { stroke: var(--ink-muted); stroke-width: 1.5; fill: none; color: var(--ink-muted); }
.d-rule { stroke: var(--ink-muted); stroke-opacity: 0.35; }
.d-brk { stroke: var(--ink-muted); stroke-width: 1.2; }
.d-loop { stroke: var(--loop); stroke-width: 1.8; fill: none; stroke-dasharray: 6 4; color: var(--loop); }
.d-scope { stroke: var(--prove); stroke-width: 1.8; fill: none; }
.d-handline { stroke: var(--prove); stroke-width: 1.6; stroke-dasharray: 3 3; }
.d-track-lead { stroke: var(--prove); stroke-width: 2.5; }
.d-track-mon { stroke: var(--handoff); stroke-width: 1.5; stroke-dasharray: 5 4; }
.d-stop { fill: var(--prove); }
/* Colour modifiers come last so they win over the text size classes above. */
.d-deals { fill: var(--deals); }
.d-delivery { fill: var(--delivery); }
.d-lead { fill: var(--prove); }
.d-acc { fill: var(--loop); }
.d-tag.lead { fill: var(--prove); }
.d-tag.muted { fill: var(--ink-muted); }
.d-om-ink { fill: var(--operating-ink); }

/* Unit method wheel. Same viewBox width and text sizes as the other diagrams. The explanation box sits
   below the wheel, inside the same frame, at every width. */
.wheelbox { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-16); }
.wheelframe { position: relative; }
.wheelwrap { overflow: hidden; }
.wheel { display: block; width: 100%; height: auto; color: var(--loop); }
.wheel text { font-family: var(--font-body); }
.wheel .arc { fill: none; stroke: var(--ink-muted); stroke-width: 1.6; opacity: 0.55; color: var(--ink-muted); transition: stroke var(--ease), opacity var(--ease); }
.wheel .arc.on { stroke: var(--navy); color: var(--navy); opacity: 1; stroke-width: 2.6; }
.wheel .loopArc,
.wheel .loopArc.on { stroke: var(--loop); color: var(--loop); opacity: 1; stroke-width: 2; stroke-dasharray: 6 4; }
.wheel .loopArc.on { stroke-width: 2.8; }
.wheel .hub { font-size: var(--diagram-size-note); letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600; fill: var(--loop); }
.wheel .wn { cursor: pointer; outline: none; }
.wheel .wn circle { fill: var(--paper); stroke-width: 2; transition: fill var(--ease); }
.wheel .wnum { font-size: var(--diagram-size-label); font-weight: 600; pointer-events: none; transition: fill var(--ease); }
.wheel .wl { font-size: var(--diagram-size-label); fill: var(--navy); }
.wheel .wn.on .wl { font-weight: 600; }
.wheel .wn:focus-visible circle { stroke: var(--blue); stroke-width: 4; }
.wheel .wn.lead circle { stroke: var(--prove); }
.wheel .wn.lead .wnum,
.wheel .wn.lead .wl { fill: var(--prove); }
.wheel .wn.mon circle { stroke: var(--handoff); stroke-dasharray: 4 3; }
.wheel .wn.mon .wnum { fill: var(--handoff); }
.wheel .wn.lead.on circle { fill: var(--prove); }
.wheel .wn.mon.on circle { fill: var(--handoff); }
.wheel .wn.on .wnum { fill: var(--paper); }
.wheel .hand { fill: var(--prove); font-size: var(--diagram-size-note); letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600; }
.wheel .handline { stroke: var(--prove); stroke-width: 1.6; stroke-dasharray: 3 3; }
.wheelbox .panel { display: none; }
.wheelbox.js .panel {
  display: block;
  padding: var(--s-16) var(--s-24);
  border: 1.5px solid var(--prove);
  border-radius: var(--radius);
  background: var(--surface);
  min-height: 9em;
  transition: opacity var(--ease);
}
.wheelbox.js.mon .panel { border-color: var(--handoff); border-style: dashed; }
.wheelbox .pn { font-size: var(--fs-small); font-weight: 600; color: var(--prove); margin-bottom: var(--s-8); }
.wheelbox.js.mon .pn { color: var(--ink-muted); }
.wheelbox.js .wlist { display: none; }
.wlist { margin: 0; padding-left: var(--s-24); }
.wlist li + li { margin-top: var(--s-8); }
.legend { font-size: var(--fs-small); color: var(--ink-muted); display: flex; flex-wrap: wrap; gap: var(--s-8) var(--s-24); }
.legend i { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: var(--s-8); vertical-align: -1px; }
.legend .l1 { background: var(--prove); }
.legend .l2 { border: 2px dashed var(--handoff); }
@media (max-width: 899px) {
  /* Numbers only on narrow screens, cropped to the wheel at 889px wide so numbers render at 14px:
     names and explanations sit in the box below. */
  .wheel { width: 889px; max-width: none; margin-left: calc(50% - 293px); }
  .wheel .wl { display: none; }
}
@media (min-width: 900px) {
  /* The wheel is centred at full diagram size (14px labels), and the explanation box sits below it. */
  .wheelframe { border-block: 1px solid var(--line); background: var(--paper); padding-bottom: var(--s-32); }
  .wheel { width: 1000px; max-width: none; margin-left: calc(50% - 330px); }
  .wheelbox.js .panel {
    width: calc(100% - 2 * var(--gutter));
    max-width: var(--reading);
    margin-inline: auto;
    min-height: 7.5em;
  }
  .legend,
  .wlist { padding-inline: var(--gutter); }
  .wlist { padding-left: calc(var(--gutter) + var(--s-24)); }
}
@media (min-width: 1120px) {
  .wheelframe { border: 1px solid var(--line); border-radius: var(--radius); }
}

/* Full-screen diagram viewer (js/diagram-zoom.js) */
.diagram-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-8) var(--s-16); }
@media (min-width: 900px) { .diagram-tools { padding-inline: var(--gutter); } }
.zoom-btn {
  font: inherit;
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1;
  min-height: 44px;
  min-width: 44px;
  padding: 0 var(--s-16);
  border-radius: var(--radius);
  cursor: pointer;
  color: var(--blue);
  background: transparent;
  border: 1.5px solid var(--blue);
  transition: background-color var(--ease), opacity var(--ease);
}
.zoom-btn:hover:not(:disabled) { background: var(--blue-tint); }
.zoom-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.scroll.zoomable { cursor: zoom-in; }
.zoom-dialog {
  position: fixed;
  inset: 0;
  width: 100vw;
  max-width: none;
  height: 100vh;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--paper);
  color: var(--navy);
}
.zoom-dialog[open] { display: flex; flex-direction: column; }
.zoom-dialog::backdrop { background: var(--paper); }
.zoom-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s-16); padding: var(--s-8) var(--s-16); border-bottom: 1px solid var(--line); }
.zoom-controls { display: flex; gap: var(--s-8); }
.zoom-stage { flex: 1 1 auto; min-height: 0; overflow: auto; display: flex; padding: var(--s-8); }
.zoom-stage .zoom-svg { display: block; flex: none; width: 100%; min-width: 0; height: auto; margin: auto; }
.zoom-hint { margin: 0; padding: var(--s-8) var(--s-16); font-size: var(--fs-note); color: var(--ink-muted); border-top: 1px solid var(--line); }
.zoom-hint:empty { display: none; }
html:has(.zoom-dialog[open]) { overflow: hidden; }


/* Call to action */
.cta .container { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-24); }
.cta .section-title { margin: 0; }

/* Insights list: left-aligned in the reading column, newest first. Date in a fixed left column on wider
   screens and above the title on phones. The title is the link out. */
.insights-list { list-style: none; margin: 0; padding: 0; max-width: var(--reading); border-top: 1px solid var(--line); }
.insight { border-bottom: 1px solid var(--line); padding-block: var(--s-24); display: grid; gap: var(--s-4); }
@media (min-width: 640px) { .insight { grid-template-columns: 128px minmax(0, 1fr); gap: var(--s-24); } }
.insight-date { font-size: var(--fs-note); line-height: 1.5; color: var(--ink-muted); padding-top: 3px; }
.insight-main { min-width: 0; }
.insight-title { font-family: var(--font-body); font-size: var(--fs-body); font-weight: 600; line-height: 1.3; margin: 0; }
.insight-title a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
.insight-title a:hover { text-decoration-thickness: 2px; }
.insight-meta { display: flex; flex-wrap: wrap; gap: var(--s-4) var(--s-16); font-size: var(--fs-note); color: var(--ink-muted); margin-top: var(--s-8); }
.insight-series { color: var(--insights); font-weight: 600; }
.insight-links { display: flex; flex-wrap: wrap; gap: var(--s-8) var(--s-24); margin-top: var(--s-8); font-size: var(--fs-small); }
.insight-links a { display: inline-flex; align-items: center; min-height: 44px; }
.insight details { margin-top: var(--s-8); }
.insight summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--blue);
  font-weight: 600;
  font-size: var(--fs-small);
}
.insight summary::-webkit-details-marker { display: none; }
.insight summary::before { content: "+"; display: inline-block; width: 1.2em; }
.insight details[open] summary::before { content: "\2212"; }
.insight .lead-in { max-width: var(--reading); }
.insight .lead-in p + p { margin-top: var(--s-16); }
.insight-note { font-size: var(--fs-note); color: var(--ink-muted); margin-top: var(--s-8); }

/* About */
.about { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-24); align-items: center; }
@media (min-width: 640px) { .about { grid-template-columns: 280px minmax(0, 1fr); gap: var(--s-48); } }
.about img { border-radius: var(--radius); width: 100%; max-width: 280px; }
.about .name { font-family: var(--font-head); font-size: var(--fs-h3); font-weight: 600; line-height: 1.2; }
.about .title { color: var(--ink-muted); margin-top: var(--s-4); }
.linkedin { display: inline-flex; align-items: center; gap: var(--s-8); min-height: 44px; margin-top: var(--s-16); font-weight: 600; }
.linkedin img { width: 28px; height: auto; }
.linkedin .li-dark { display: none; }
:root:not([data-theme="light"]) .linkedin .li-light { display: none; }
:root:not([data-theme="light"]) .linkedin .li-dark { display: block; }

/* Footer */
.site-footer { background: var(--paper); border-top: 1px solid var(--line); padding-block: var(--s-48); }
.site-footer .container { display: flex; flex-direction: column; gap: var(--s-24); }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s-8) var(--s-24); }
/* Same logo and links as the header: logo on top, links under it, the logo no wider than the links, links the same size as the top menu. */
.footer-block { display: grid; gap: var(--s-4); width: max-content; max-width: 100%; justify-items: stretch; }
.footer-block .brand { width: 0; min-width: 100%; }
.footer-block .brand img { width: 100%; height: auto; }
.footer-block .brand .wordmark { font-size: var(--fs-small); }
.site-footer li a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; font-size: var(--fs-label); font-weight: 600; color: var(--navy); text-decoration: none; }
.site-footer li a:hover { text-decoration: underline; }
.site-footer .footer-block ul { flex-wrap: nowrap; gap: var(--s-24); justify-content: space-between; }
.site-footer .copyright { font-size: var(--fs-micro); color: var(--ink-muted); }

/* Plain pages (legal, privacy, insights, contact) */
.page { padding-block: var(--section-pad); }
.page .container > * + * { margin-top: var(--s-24); }
.prose { max-width: var(--reading); }
.prose h2 { font-size: var(--fs-h3); margin-top: var(--s-48); }
.prose h2 + p { margin-top: var(--s-16); }
.prose p + p { margin-top: var(--s-16); }

/* Get in touch form */
.form-col { max-width: 720px; }
.form { display: flex; flex-direction: column; gap: var(--s-24); margin-top: var(--s-32); }
.field { display: flex; flex-direction: column; gap: var(--s-8); }
.field label { font-weight: 600; font-size: var(--fs-label); }
.field select,
.field input {
  font: inherit;
  color: var(--navy);
  background: var(--paper);
  border: 1px solid var(--ink-muted);
  border-radius: var(--radius);
  min-height: 48px;
  padding: 10px 14px;
  width: 100%;
}
.field select:focus-visible,
.field input:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.field [aria-invalid="true"] { border-color: var(--error); border-width: 2px; }
.field .error { display: none; color: var(--error); font-size: var(--fs-small); align-items: center; gap: var(--s-8); }
.field .error.show { display: flex; }
.field .error svg { flex: none; }
.turnstile-slot { min-height: 65px; }
.fine { font-size: var(--fs-note); color: var(--ink-muted); }
.notice {
  border: 1.5px dashed var(--error);
  border-radius: var(--radius);
  padding: var(--s-16);
  font-size: var(--fs-small);
}
.booking { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); min-height: 640px; margin-top: var(--s-24); }
[hidden] { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* Text is left-aligned at every width, with no justification and no automatic hyphenation.
   The hero, header, footer and form stay centred as composed blocks. */
body { text-align: left; hyphens: manual; }
.hero { text-align: center; }
.hero .second, .hero .descriptor { margin-inline: auto; }
.hero-title { margin-inline: auto; }
.btns, .site-nav ul, .site-footer ul, .zoom-controls { justify-content: center; }
.site-footer { text-align: center; }
.site-footer .container { align-items: center; justify-content: center; }
.about { grid-template-columns: minmax(0, 1fr); justify-items: start; }
.about-email { font-size: var(--fs-label); line-height: 1.5; margin-top: var(--s-4); }
.wlist { padding-inline-start: 1.25em; }
.field { align-items: center; text-align: center; }
.field select, .field input { text-align: center; text-align-last: center; }
.cta .container { flex-direction: column; align-items: flex-start; }
.cta .btns { justify-content: flex-start; }
.cta .container > * + * { margin-top: 0; }
.section--surface .units li { background: var(--paper); }

/* Menu spreads evenly across the logo width (must come after the centring rules above). */
.masthead .site-nav ul { flex-wrap: nowrap; gap: 0; justify-content: space-between; }
.masthead .site-nav a { min-width: 44px; justify-content: center; }

/* Phones and small tablets: one short sticky bar, about 56px high. The bullseye mark on the left (in both themes),
   the menu on the right. The full logo and the stacked menu return at 760px. */
@media (max-width: 759.98px) {
  .site-header .container { padding-block: 6px; }
  .masthead { display: flex; align-items: center; justify-content: space-between; gap: var(--s-8); width: 100%; }
  .site-nav { width: auto; min-width: 0; }
  .site-header .brand .brand-logo,
  .site-header .brand .wordmark { display: none; }
  .site-header .brand .brand-mark { display: block; width: 32px; height: 32px; }
  .site-header .brand { min-height: 44px; min-width: 44px; justify-content: flex-start; }
  .masthead .site-nav ul { gap: 0 12px; justify-content: flex-end; }
}

/* One text size inside boxes: the size of "Telecom and mobile data" (--fs-small, 14px). Titles keep weight 600. */
.units b, .units span,
.card, .card .card-label, .card h3, .card dt, .card dd,
.wheelbox .panel, .wheelbox .pn, .wheelbox .pt { font-size: var(--fs-small); line-height: 1.5; }
.units b, .card h3 { font-weight: 600; }

/* Palette accents (three light colours from the bokeh image): aqua rules, a blue footer edge and a blush call-to-action band. */

/* Hero logo mark: the teal arc spins up with acceleration, then settles. The discs are concentric and round,
   so rotating the whole mark reads as only the arc turning. Owner-approved exception to the no-rotation and
   no-animation rules; it plays once and is skipped for reduced motion. */
.hero-copy { min-width: 0; width: 100%; }
.hero-mark { display: block; width: 140px; height: auto; margin: var(--s-32) auto 0; }
@media (min-width: 900px) { .hero-mark { width: 200px; } }
@keyframes mark-spin {
  0%   { transform: rotate(0deg);    animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.6); }
  65%  { transform: rotate(1080deg); animation-timing-function: cubic-bezier(0.1, 0.6, 0.3, 1); }
  100% { transform: rotate(1440deg); }
}
@media (prefers-reduced-motion: no-preference) {
  .hero-mark { animation: mark-spin 3.2s 0.4s both; }
}

/* Pattern transfer and call-to-action bands: the logo mark as an oversized, faint, still background. */
.pattern-band { position: relative; overflow: hidden; }
.pattern-band > .container { position: relative; z-index: 1; }
.pattern-band::before {
  content: "";
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 50%;
  width: max(1000px, 90vw);
  aspect-ratio: 1;
  translate: -50% -50%;
  background: url("/img/logo-mark.png") center / contain no-repeat;
  opacity: 0.14;
  pointer-events: none;
}


/* Pattern box titles in capitals, like DEALS in the practice diagram. */
.units b { text-transform: uppercase; letter-spacing: 0.06em; }

/* Larger boxes: the pattern boxes and the What you get cards use 16px text with more padding. */
.units li { padding: var(--s-24) var(--s-24) var(--s-32); gap: var(--s-8); }
.units b, .units span { font-size: var(--fs-label); line-height: 1.5; }
.card { padding: var(--s-32); }

/* What you get cards: the promise line (h3) is the strongest text. The practice name sits above it in small
   practice-coloured caps, the field labels are small, regular and muted, and the body stays at 16px. */
.card .card-label { font-size: var(--fs-small); line-height: 1.4; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.card h3 { font-size: var(--fs-h3); line-height: 1.3; font-weight: 600; color: var(--navy); margin-bottom: var(--s-16); }
.card dl { gap: var(--s-24); }
.card dt { font-size: var(--fs-label); line-height: 1.4; font-weight: 400; color: var(--ink-muted); text-transform: none; letter-spacing: 0; }
.card dd { font-size: var(--fs-body); line-height: 1.55; font-weight: 400; color: var(--navy); margin-top: var(--s-4); }

/* Practice colour: a square 4px bar inside the card, above the label, so the 8px corners stay clean. */
.card { border-top: 1px solid var(--line); }
.card::before { content: ""; display: block; height: 4px; background: var(--card-colour, var(--line)); margin-bottom: var(--s-8); }

/* Hero headline in Barlow 600, large (up to 72px), wrapping to two lines on phones (owner request). */
.hero-title, .hero-title .l1 { font-weight: 600; }
/* The hero's short statement stays centred with the rest of the hero. */
.hero .second { text-align: center; }

/* About: the photo is exactly as wide as the name. */
.about { gap: var(--s-8); }
.about-id { display: grid; gap: var(--s-16); width: max-content; max-width: 100%; justify-items: stretch; }
.about-id img { width: 0; min-width: 100%; max-width: none; height: auto; margin: 0; }
.about .title { font-weight: 400; }

/* Contact block: larger title and email under the name. */
.about .title { font-size: var(--fs-body); }
.about-email { font-size: var(--fs-label); }



/* The hero sentence now opens with "Licensed, priced and structured to work:" and keeps the original sentence style. */
.hero .second { max-width: 46ch; margin-top: var(--s-32); }

/* Alignment rule (design system section 6): structural elements are centred, reading text, cards and lists are
   left-aligned. Section headings and their short one or two line intros are centred at every width. Longer
   paragraphs, the Insights list and the cards keep left-aligned text in a column centred on the same axis. */
.section > .container > h2,
.page h1 { text-align: center; }
.plain-line, .lede.intro { text-align: center; margin-inline: auto; }
.lede, .insights-list { margin-inline: auto; }
.cta .container { align-items: center; text-align: center; }
.cta .btns { justify-content: center; }

/* About on the homepage and the Get in touch page: centred as a whole. */
#about { text-align: center; }
#about .about { justify-items: center; }
#about .linkedin { justify-content: center; }
.form-col { margin-inline: auto; text-align: center; }
.form-col .field .error.show { justify-content: center; }
#insights .container > p:last-child { max-width: var(--reading); margin-inline: auto; }
.form-col section > .lede,
.form-col section > .notice { margin-top: var(--s-16); }

/* Pattern cards: centred text. Packets keeps the purple frame, Streams takes the logo teal (--loop), and the
   open card (Tokens, the next units) has a thicker dashed grey frame. */
.units li { align-items: center; text-align: center; }
.units li.u-streams { border-color: var(--loop); }
.units li.open { border-style: dashed; border-width: 3px; border-color: var(--handoff); }

/* A "Learn more" button centred under a section (same style as "Read the insights"). */
.section-btns { justify-content: center; margin-top: var(--s-32); }

/* Where we help: three cards side by side on wide screens, stacked on narrower ones. */
@media (min-width: 760px) { .cards { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 960px) { .cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.card--operating { --card-colour: var(--operating-border); }
/* The yellow is too light for text: the Operational frameworks label stays in the text colour. */
.card--operating .card-label { color: var(--navy); }

/* Method page heading. */
.method-head { padding-bottom: 0; }
.method-head h1 { text-align: center; }

/* Insights series: The Token Economy in green (logo teal), The Quantum Economy in purple. The colour carries the
   series label and the filter button; titles stay plain text colour. */
.insight-series.series--token-economy { color: var(--loop); }
.insight-series.series--quantum-economy { color: var(--prove); }

/* Series filter on the Insights page. */
.series-filter { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-8) var(--s-16); }
.series-filter[hidden] { display: none; }
.series-btn {
  min-height: 44px;
  padding: 10px 16px;
  border-radius: var(--radius);
  border: 1.5px solid var(--line);
  background: transparent;
  color: var(--navy);
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--ease), border-color var(--ease);
}
.series-btn.series--token-economy { color: var(--loop); }
.series-btn.series--quantum-economy { color: var(--prove); }
.series-btn:hover { border-color: currentColor; }
.series-btn[aria-pressed="true"] { border-color: currentColor; background: var(--surface); }
.series-btn:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.insight[hidden] { display: none; }

/* Pattern cards arrive in step with the hero logo spin (owner-approved exception to the motion rule).
   js/pattern-sync.js waits until the cards first scroll into view, then replays the logo spin (3.2s) and fades
   Packets, Streams, then Tokens, the next units in gently, the same fade as the Where we help cards (card-fade,
   1.6s each, an 8px rise), spaced 0.8s apart so the last card settles at 3.2s, as the spin stops. Without JavaScript, or for visitors who prefer reduced motion, the cards
   simply show. */
.units.is-waiting li { opacity: 0; transform: translateY(8px); }
.units.is-arriving li { animation: card-fade 1.6s cubic-bezier(0.25, 0.1, 0.25, 1) both; }
.units.is-arriving li:nth-child(2) { animation-delay: 0.8s; }
.units.is-arriving li:nth-child(3) { animation-delay: 1.6s; }

/* Where we help, three columns: every card shares the same rows through subgrid, so the label, the promise line,
   and each "Who it is for", "What we do" and "What you leave with" start on the same line in all three cards,
   and the cards are exactly the same height. The promise lines are set a little smaller so each fits on one line. */
@media (min-width: 960px) {
  .card { display: grid; grid-template-rows: subgrid; grid-row: span 9; row-gap: 0; align-content: start; }
  .card dl { display: grid; grid-template-rows: subgrid; grid-row: span 6; row-gap: 0; margin-top: var(--s-16); }
  .card dl > div { display: contents; }
  .card .card-label { margin-top: var(--s-8); }
  .card h3 { margin-top: var(--s-16); margin-bottom: 0; font-size: var(--fs-body); white-space: nowrap; }
  .card dt { margin-top: var(--s-24); }
  .card dl > div:first-child dt { margin-top: 0; }
}

/* Where we help cards fade in gently the first time they scroll into view (js/cards-reveal.js): Deal frameworks,
   then Insights, then Operational frameworks, 1.6s each, 0.6s apart, with only an 8px rise. Owner-approved
   exception to the motion rule, offered for comparison with the pattern cards' slide-in. Without JavaScript or
   with reduced motion the cards simply show. */
@keyframes card-fade {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.cards.is-waiting .card { opacity: 0; transform: translateY(8px); }
.cards.is-revealing .card { animation: card-fade 1.6s cubic-bezier(0.25, 0.1, 0.25, 1) both; }
.cards.is-revealing .card:nth-child(2) { animation-delay: 0.6s; }
.cards.is-revealing .card:nth-child(3) { animation-delay: 1.2s; }

/* Choose how we engage: the intro runs the full width of the container, the same width as the Where we help
   cards, so it reads as one sentence in as few lines as possible. It wraps naturally on narrow screens. */
.lede.lede--wide { max-width: none; }

/* More room between each card's promise line and "Who it is for". */
.card h3 { margin-bottom: var(--s-24); }
@media (min-width: 960px) { .card h3 { margin-bottom: 0; } .card dl { margin-top: var(--s-32); } }

/* Engagement picture: the three stage titles are larger, in capitals, on two lines (owner request). */
.d-stage { letter-spacing: 0.06em; }
.d-sub { font-size: var(--fs-note); font-weight: 600; letter-spacing: 0.06em; fill: var(--navy); }

/* The email link's underline sits below the descenders, so skip-ink never leaves a stray mark before the "g". */
.about-email a { text-underline-offset: 0.3em; text-decoration-skip-ink: none; }


/* Text for screen readers only (for example, "opens LinkedIn in a new tab"). */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* Phone layouts of the wide diagrams (src/diagrams/*-stack.html). Below 900px the sideways-scrolling frame is
   replaced by the same content stacked vertically; "See the full picture" opens the original diagram in the
   full-screen viewer. From 900px the stacked version is hidden. Same tokens and type as the diagrams. */
.stack { display: none; }
@media (max-width: 899px) {
  .has-stack > .scroll,
  .has-stack .diagram-tools,
  .has-stack > .swipe-hint { display: none; }
  .has-stack .stack { display: grid; gap: var(--s-8); padding-inline: var(--gutter); text-align: left; }
}
.stack p { margin: 0; }
.stack .t-deals { color: var(--deals); }
.stack .t-delivery { color: var(--delivery); }
.stack-open {
  display: none;
  justify-self: center;
  margin-top: var(--s-16);
  min-height: 44px;
  padding: 10px 16px;
  border-radius: var(--radius);
  border: 1.5px solid var(--blue);
  background: transparent;
  color: var(--blue);
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 600;
  cursor: pointer;
}
.stack-open.ready { display: inline-flex; align-items: center; }
.stack-open:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

/* Practice picture, stacked. */
.pbar { border: 1.5px solid var(--line); border-radius: var(--radius); padding: var(--s-16); text-align: center; background: var(--surface); }
.pbar--insights { border-color: var(--insights); background: color-mix(in srgb, var(--insights) 12%, var(--paper)); }
.pbar-title, .pbox-title { font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--navy); }
.pflow, .plink, .pnote, .pfoot { font-size: var(--fs-small); color: var(--ink-muted); }
.pflow { margin-top: var(--s-4); }
.plink { text-align: center; }
.pbox { border: 1.5px solid var(--line); border-radius: var(--radius); padding: var(--s-16); background: var(--paper); font-size: var(--fs-small); line-height: 1.5; }
.pbox--deals { border-color: var(--deals); background: color-mix(in srgb, var(--deals) 8%, var(--paper)); }
.pbox--deals .pbox-title { color: var(--deals); }
.pbox--delivery { border-color: var(--delivery); background: color-mix(in srgb, var(--delivery) 8%, var(--paper)); }
.pbox--delivery .pbox-title { color: var(--delivery); }
.pbox--om { border-color: var(--operating-border); background: var(--operating); color: var(--operating-ink); }
.pbox--om .pbox-title, .pbox--om dt, .pbox--om dd { color: var(--operating-ink); }
.pbox dl { margin: var(--s-8) 0 0; display: grid; gap: var(--s-4); }
.pbox dt { font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-muted); margin-top: var(--s-8); }
.pbox dd { margin: 0; color: var(--navy); }
.pbar--unit { display: grid; gap: var(--s-4); font-size: var(--fs-small); }
.pfoot { margin-top: var(--s-4); text-align: center; }

/* Five steps, stacked: one vertical rail (see the engagement rail below), steps 1 to 3 purple, 4 and 5 grey. */
.skey { font-size: var(--fs-small); color: var(--ink-muted); }
.phase-name { font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); }
.sstep { display: flex; gap: var(--s-8); align-items: flex-start; color: var(--navy); }
.sstep small { display: block; font-size: var(--fs-small); color: var(--ink-muted); }
.sstep.lead { color: var(--prove); }
.snum { flex: none; display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--prove); font-weight: 600; font-size: var(--fs-small); color: var(--prove); background: var(--paper); }
.sstep.pop .snum { background: var(--prove); color: var(--paper); }
.mon .snum { border: 2px dashed var(--handoff); color: var(--handoff); }
.sstep.mon { color: var(--navy); }
.sthread { color: var(--navy); }
.sthread b { display: inline-block; min-width: 4.8em; font-weight: 600; }
.phase-hand, .ehand { text-align: center; font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--prove); border-top: 1.5px dashed var(--prove); padding-top: var(--s-4); }
.sloop { font-size: var(--fs-small); font-weight: 600; color: var(--loop); text-align: center; }
.sloop::before { content: "\21BA  "; }

/* Engagement, stacked: the five-step track, then one card per stage. */
.estage { border: 1px solid var(--line); border-radius: var(--radius); padding: var(--s-24); background: var(--surface); display: grid; gap: var(--s-8); font-size: var(--fs-label); line-height: 1.5; color: var(--navy); }
.estage::before { content: ""; display: block; height: 4px; background: var(--prove); }
.estage-title { font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.4; }
.estage-sub { display: block; font-size: var(--fs-note); margin-top: var(--s-4); }
.eleave { margin-top: var(--s-16) !important; font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-muted); }

/* Method page: one orienting line and three jump links under the heading. */
.method-head .lede.intro { margin-top: var(--s-16); }
.jump { margin-top: var(--s-24); }
.jump ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-8) var(--s-24); }
.jump a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }

/* Get in touch: the heading, intro and notice stay centred; the form itself is a narrow centred column with
   left-aligned labels, fields, button and privacy note, which scans faster than centred fields. */
.form-col .form { max-width: 480px; margin-inline: auto; text-align: left; }
.form-col .field { align-items: stretch; text-align: left; }
.form-col .field select,
.form-col .field input { text-align: left; text-align-last: left; }
.form-col .form .btns { justify-content: flex-start; }
.form-col .field .error.show { justify-content: flex-start; }
.wheelbox .legend { justify-content: center; }
.sthread { display: grid; grid-template-columns: 5em minmax(0, 1fr); gap: var(--s-8); }
.sthread b { min-width: 0; }

/* Method, Insights and Get in touch pages take the About section's background (--surface). Diagram frames
   and the wheel keep --paper so they still read as panels. */
.method-page, .page--surface { background: var(--surface); }
.method-page .scroll { background: var(--paper); }

/* Sticky sub-menus: the Method section buttons and the Insights series filter stay pinned under the header
   while scrolling, so they are always within reach. --header-h is the header's height at each width. */
:root { --header-h: 57px; }
@media (min-width: 760px) { :root { --header-h: 119px; } }
.jump, .series-filter {
  position: sticky;
  top: calc(var(--header-h) - 1px);
  z-index: 15;
  background: transparent;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  padding-block: var(--s-8);
  border-bottom: 1px solid var(--line);
}
.series-filter { margin-inline: calc(var(--gutter) * -1); padding-inline: var(--gutter); }
.jump { margin-top: var(--s-24); }
html:has(.jump), html:has(.series-filter) { scroll-padding-top: calc(var(--header-h) + 80px); }

/* Method section buttons: the same style as the Insights series buttons; the section being read is marked. */
.jump ul { gap: var(--s-8) var(--s-16); }
.jump a {
  min-height: 44px;
  padding: 10px 16px;
  border-radius: var(--radius);
  border: 1.5px solid var(--line);
  color: var(--navy);
  font-size: var(--fs-label);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--ease), border-color var(--ease);
}
.jump a:hover { border-color: currentColor; }
.jump a[aria-current="true"] { border-color: currentColor; background: var(--paper); }
.series-btn[aria-pressed="true"] { background: var(--paper); }
/* On phones the pinned button rows stay one line high and swipe sideways instead of wrapping. */
@media (max-width: 759px) {
  .jump ul, .series-filter { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; scrollbar-width: none; }
  .jump li, .series-btn { flex: none; }
  .jump a, .series-btn { white-space: nowrap; }
}

/* About: the owner's name in regular weight (owner request), still at the H2 size. */
.about .name { font-weight: 400; }

/* Engagement picture: each term sits in its own box (surface fill, 1px line, square purple bar along the top),
   and the handoff is marked by three dots above the track that stop at it. */
.d-stagebox { fill: var(--surface); stroke: var(--line); stroke-width: 1; }
.d-stagebar { fill: var(--prove); }
.d-handdot { fill: var(--prove); }

/* Unit method explanation box: larger, centred text for all five steps (owner request). The box is as tall as
   the longest step (js/wheel.js), and on desktop a little wider so the longer explanations stay short. */
.wheelbox.js .panel { text-align: center; padding: var(--s-24) var(--s-32); }
.wheelbox .pn { font-size: var(--fs-body); line-height: 1.4; margin-bottom: var(--s-8); }
.wheelbox .pt { font-size: var(--fs-body); line-height: 1.55; color: var(--navy); }
@media (min-width: 900px) { .wheelbox.js .panel { max-width: 760px; min-height: 0; } }
@media (max-width: 899px) { .wheelbox.js .panel { padding: var(--s-16) var(--s-16); } }

/* Five-steps picture: the Centre of Excellence bracket under steps 3 to 5. */
.d-bracket { stroke: var(--ink-muted); stroke-width: 1.2; }

/* Five steps, phone version: the Centre of Excellence note under the phases. */
.scoe { border: 1.5px solid var(--ink-muted); border-radius: var(--radius); padding: var(--s-16); font-size: var(--fs-small); line-height: 1.5; color: var(--navy); display: grid; gap: var(--s-4); }
.scoe-title { font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); }
.scoe-title span { font-weight: 400; text-transform: none; letter-spacing: 0; }

/* Phone practice picture: the Operating model box always uses the dark operating ink (the same as the wide
   picture), so its text stays readable in dark mode. */
.pbox.pbox--om .pbox-title,
.pbox.pbox--om dt,
.pbox.pbox--om dd { color: var(--operating-ink); }

/* Get in Touch: the call details under the heading (replaces the old intro line). */
.call-info { display: grid; gap: var(--s-4); justify-items: center; margin-top: var(--s-16); text-align: center; }
.call-info span { color: var(--ink-muted); }

/* Get in Touch: Send is centred and sits close to the last field. The space reserved for the Turnstile widget
   (so nothing shifts when it loads) now sits below the button and the privacy note, not above the button. */
.form-col .form .btns { justify-content: center; }
.form-col .form .fine { text-align: center; }

/* Unit method explanation: no box. The text sits straight on the white frame behind the wheel, and the empty
   space under it is kept to the height of the longest of the five explanations (js/wheel.js). */
.wheelbox.js .panel,
.wheelbox.js.mon .panel,
.wheelbox.js.lead .panel { background: transparent; border: 0; border-radius: 0; padding: var(--s-8) var(--s-16) 0; }
.wheelframe { padding-bottom: var(--s-16); }
@media (min-width: 900px) {
  .wheelframe { padding-bottom: var(--s-16); }
  .wheelbox.js .panel { max-width: 880px; padding-inline: var(--s-32); }
}

/* Hero: the one-line job under the existing sub-line. */

/* Method: the spine line (unit, owner, licence) under each step's explanation. */
.wheelbox .ps { font-size: var(--fs-body); font-weight: 600; line-height: 1.4; margin-top: var(--s-8); color: var(--prove); }
.wheelbox.js.mon .ps { color: var(--ink-muted); }
.wheelbox .ps:empty { display: none; }
.wlist .spine { display: block; font-weight: 600; color: var(--prove); }





/* About: name, title, email and LinkedIn sit closer together (owner request). */
.about { gap: 0; }
.about-id { gap: var(--s-8); }
.about .name { line-height: 1.15; }
.about .title { line-height: 1.25; margin-top: 0; }
.about .about-email { line-height: 1.3; margin-top: var(--s-4); }
.about .linkedin { margin-top: var(--s-4); min-height: 44px; }

/* Five steps, phone version: the Unit, Licence and Owner labels, in the same small purple style as the picture's tags. */
.sstep small.slabel { color: var(--prove); font-weight: 600; }

/* Touch targets: the logo links and the LinkedIn icon reach 44px without changing how anything looks.
   The extra height is padding cancelled by a negative margin, and links later in the page paint above it. */
.site-header .brand { padding-block: 3px; margin-block: -3px; }
.footer-block .brand { padding-block: 10px; margin-block: -10px; }
.linkedin { min-width: 44px; justify-content: center; }


/* Engagement: a Project is purple (steps we lead), the Fractional block is teal (it carries on with the loop).
   The coloured header, bar, bracket and diamond of each block follow its type. */
.d-bracket.proj { stroke: var(--prove); }
.d-bracket.frac { stroke: var(--loop); color: var(--loop); }
.d-stagebar.proj { fill: var(--prove); }
.d-stagebar.frac { fill: var(--loop); }
.d-stagehead.proj { fill: color-mix(in srgb, var(--prove) 11%, var(--surface)); }
.d-stagehead.frac { fill: color-mix(in srgb, var(--loop) 13%, var(--surface)); }
.d-stop.proj { fill: var(--prove); }
.d-stop.frac { fill: var(--loop); }
.d-ph.d-tagtext { font-weight: 600; letter-spacing: 0.1em; }
.d-ph.d-tagtext.proj { fill: var(--prove); }
.d-ph.d-tagtext.frac { fill: var(--loop); }

/* Phone version: the same coloured header across the top of each card. */
.estage--project, .estage--fractional { padding-top: 0; overflow: hidden; }
.estage--project::before, .estage--fractional::before { display: none; }
.estage .estage-tag { margin: 0 calc(-1 * var(--s-24)) var(--s-8); padding: var(--s-8) var(--s-24); border-top: 4px solid var(--c); background: color-mix(in srgb, var(--c) 11%, var(--surface)); color: var(--c); font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; }
.estage--project { --c: var(--prove); }
.estage--fractional { --c: var(--loop); }

/* Engagement picture: steps 4 and 5 sit on a continuous grey line with solid circles, and the timeline ends in an
   arrow like the longer-term bracket. Only the feedback loop stays dashed. */
.d-track-solid { stroke: var(--handoff); stroke-width: 2.5; color: var(--handoff); }
.d-node.mon.solid { stroke-dasharray: none; stroke-width: 2.5; }

/* Engagement intro is centred. */
#rules-title + .lede { text-align: center; }

/* Phone engagement: one vertical rail. Purple through steps 1 to 3, a dotted handoff, then grey steps 4 and 5 that
   end in an arrow. Each block's rail fills in as it scrolls into view; the cards fade up. Without JavaScript or
   with reduced motion everything is simply drawn. */
.vrail { list-style: none; margin: 0; padding: 0; --rail: 2.5px; }
.vblock { position: relative; padding: 0 0 var(--s-24) 44px; --p: 1; --c: var(--prove); }
.vblock--fractional { --c: var(--handoff); }
.vblock::before, .vblock::after { content: ""; position: absolute; left: 15px; top: 14px; bottom: 0; width: var(--rail); }
.vblock::before { background: var(--line); }
.vblock::after { background: var(--c); transform: scaleY(var(--p)); transform-origin: top; }
.vblock--end { padding-bottom: var(--s-16); }
.vblock--end::before, .vblock--end::after { bottom: 6px; }
.vsteps { list-style: none; margin: 0 0 var(--s-8); padding: 0; display: grid; gap: var(--s-8); font-size: var(--fs-small); color: var(--prove); }
.vsteps.mon { color: var(--ink-muted); }
.vsteps li { position: relative; display: flex; align-items: center; min-height: 32px; }
.vsteps .snum { position: absolute; left: -44px; top: 2px; width: 32px; height: 32px; z-index: 1; }
.vsteps.mon .snum { border-style: solid; }
.vhand { position: relative; padding: var(--s-16) 0 var(--s-16) 44px; font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--prove); }
.vhand::before { content: ""; position: absolute; left: 15px; top: 0; bottom: 0; border-left: var(--rail) dotted var(--handoff); }
.varrow { position: absolute; left: 10px; bottom: 0; border-top: 10px solid var(--handoff); border-inline: 6px solid transparent; width: 0; height: 0; }
.vblock .estage { margin: 0; }
.vrail.is-armed .vblock .estage { opacity: 0; transform: translateY(14px); transition: opacity 0.5s ease, transform 0.5s ease; }
.vrail.is-armed .vblock.is-in .estage { opacity: 1; transform: none; }
.vrail.is-armed .vblock::after { transition: transform 0.15s linear; }

/* Theme switch in the footer. */
.theme-toggle { align-self: center; display: inline-flex; align-items: center; gap: var(--s-8); min-height: 44px; padding: 0 var(--s-16); border: 1.5px solid var(--line); border-radius: var(--radius); background: transparent; color: var(--navy); font-family: var(--font-body); font-size: var(--fs-label); font-weight: 600; cursor: pointer; }
.theme-toggle:hover { border-color: var(--blue); }
.theme-toggle:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

/* About: name, title and email sit the same distance apart. */
.about .title, .about .about-email { margin-top: var(--s-4); }

/* Page texture: the blurred-light photo (design/background.jpg, resized to site/img) fixed at the very back. It only
   shows in the side margins and fades to nothing toward the centre where the text sits; header, footer, cards and
   the surface bands are solid and cover it, so it never lies under a logo, a box or a block of text. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: url("/img/background.jpg") center / cover no-repeat;
  opacity: var(--bg-op, 0.3);
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0.85) 12%, rgba(0, 0, 0, 0.3) 28%, rgba(0, 0, 0, 0.3) 72%, rgba(0, 0, 0, 0.85) 88%, #000 100%);
  mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0.85) 12%, rgba(0, 0, 0, 0.3) 28%, rgba(0, 0, 0, 0.3) 72%, rgba(0, 0, 0, 0.85) 88%, #000 100%);
}
@media print { body::before { display: none; } }

/* Same texture on every page, including the pages with a tinted background (Method, Insights, Contact, legal):
   those tints are now slightly see-through so the texture shows in the margins. */
body { --bg-op: 0.3; }
:root[data-theme="light"] body { --bg-op: 0.16; }
.method-page, .page--surface { background: color-mix(in srgb, var(--surface) 78%, transparent); }

/* The texture arrives with the logo: same 3.2s, same 0.4s delay, so the page settles as the mark does. */
@keyframes bg-arrive {
  from { opacity: 0; transform: scale(1.05); }
  to   { opacity: var(--bg-op, 0.3); transform: none; }
}
@media (prefers-reduced-motion: no-preference) {
  body::before { animation: bg-arrive 3.2s 0.4s both cubic-bezier(0.25, 0.1, 0.25, 1); }
}

/* Logo mark with a little depth: a soft shadow and a thin light edge lift it off the page. */

/* The mark sits to the left of every heading at the height of its capital letters; heading and mark are centred as one. */
h1:not(.hero-title)::before, h2::before {
  content: "";
  display: inline-block;
  width: 0.72em;
  height: 0.72em;
  margin-right: 0.3em;
  background: url("/img/logo-mark.png") center / contain no-repeat;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
}

/* Hero mark with a fine grain across the whole mark (an SVG noise filter, see index.html) and the soft shadow it had
   before. The grain turns with the arc; it is only a few per cent of tone, so it reads as texture, not noise. */
.grain-defs { position: absolute; width: 0; height: 0; }
.hero-mark { filter: url(#mark-grain) drop-shadow(0 1px 0 rgba(255, 255, 255, 0.22)) drop-shadow(0 10px 14px rgba(0, 0, 0, 0.32)); }

/* Light mode: the photo is paler than the page, so at normal blend it laid a grey haze over it. Multiplying darkens
   the page with the photo's blues instead and removes the haze. */
:root[data-theme="light"] body { --bg-op: 0.75; }
:root[data-theme="light"] body::before { mix-blend-mode: multiply; }

/* Light mode, darker still: a neutral tint under the photo and a stronger centre, so the whole page sits a clear step
   below the header and footer. Text contrast is unchanged for the dark text roles (checked on the darkest area). */
:root[data-theme="light"] body { --bg-op: 0.8; }
:root[data-theme="light"] body::before {
  background: linear-gradient(rgba(100, 100, 100, 0.1), rgba(100, 100, 100, 0.1)), url("/img/background.jpg") center / cover no-repeat;
  filter: sepia(0) saturate(0.9) brightness(0.9);
  -webkit-mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0.85) 12%, rgba(0, 0, 0, 0.3) 28%, rgba(0, 0, 0, 0.3) 72%, rgba(0, 0, 0, 0.85) 88%, #000 100%);
  mask-image: linear-gradient(90deg, #000 0, rgba(0, 0, 0, 0.85) 12%, rgba(0, 0, 0, 0.3) 28%, rgba(0, 0, 0, 0.3) 72%, rgba(0, 0, 0, 0.85) 88%, #000 100%);
}

/* Insight titles: plain text colour (white in dark, dark in light), regular weight, no underline at rest. They
   underline on hover and keyboard focus so they still read as links. */
.insight-title { font-weight: 400; }
.insight-title a { color: var(--navy); text-decoration: none; }
.insight-title a:hover, .insight-title a:focus-visible { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; }

/* Footer stays at the foot of the window on short pages (Insights, Contact, legal). */
body { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
body > main { flex: 1 0 auto; }
body > .site-footer { flex: none; }

/* The Tech Economy series: the logo blue. */
.insight-series.series--tech-economy, .series-btn.series--tech-economy { color: var(--blue); }

/* More space above "Deliverable" on the phone cards. */
.estage .eleave { margin-top: var(--s-32) !important; }

/* AI example on a phone: the same vertical rail as the engagement picture. Purple through steps 1 to 3, a dotted
   handoff, grey steps 4 and 5 that end in an arrow. Generous space between steps; the phase names sit on the rail. */
.vrail--steps .vblock { padding-bottom: var(--s-32); }
.vrail--steps .vblock--end { padding-bottom: var(--s-24); }
.vrail--steps .vblock::before, .vrail--steps .vblock::after { top: 0; }
.vrail--steps .vblock--first::before, .vrail--steps .vblock--first::after { top: 46px; }
.vrail--steps .vblock--end::before, .vrail--steps .vblock--end::after { bottom: 6px; }
.vblock--mon { --c: var(--handoff); }
.vrail--steps .phase-name { margin: 0 0 var(--s-8); font-size: var(--fs-small); }
.vstep { position: relative; display: block; min-height: 32px; margin: 0 0 var(--s-8); font-size: var(--fs-label); line-height: 1.45; color: var(--navy); }
.vstep.lead { color: var(--prove); }
.vstep .snum { position: absolute; left: -44px; top: 0; width: 32px; height: 32px; z-index: 1; }
.vstep.pop .snum { background: var(--prove); color: var(--paper); }
.vstep-t { display: block; padding-top: 3px; }
.vstep small { display: block; font-size: var(--fs-small); color: var(--ink-muted); }
.vstep small.slabel { color: var(--prove); font-weight: 600; }
.vrail--steps .sthread { margin: 0; font-size: var(--fs-small); }
.vrail--steps .sthread + .sthread { margin-top: var(--s-4); }
.vrail--steps .vhand { padding-block: var(--s-24); }
.stack--steps .scoe { margin-top: var(--s-24); }
.stack--steps .sloop { margin-top: var(--s-16); }

/* About: the photo is exactly as wide as the email address under it. The block is as wide as its widest line (the
   email), and the photo takes that width without adding to it. */
#about .about { width: max-content; max-width: 100%; margin-inline: auto; justify-items: stretch; }
#about .about-id, #about .about-text { display: grid; justify-items: center; width: 100%; justify-self: stretch; }
#about .about img.owner, #about .about-id img { width: 0; min-width: 100%; max-width: none; height: auto; }
#about .about-id { gap: var(--s-16); }

/* Light mode: the oversized bullseye behind "Pattern Recognition" and "Start with a Conversation" was too washed.
   Stronger and a little more saturated; the beige stays. Navy text on it is still above 6:1. */
:root[data-theme="light"] .pattern-band::before { opacity: 0.3; filter: saturate(1.3); }

/* AI example: the Deals and Delivery rows are paths, each with arrows in its own colour. */
.d-flow.deals { stroke: var(--deals); color: var(--deals); }
.d-flow.delivery { stroke: var(--delivery); color: var(--delivery); }
.mk-deals { fill: var(--deals); }
.mk-delivery { fill: var(--delivery); }
.d-flow.deals, .d-flow.delivery { stroke-width: 2; }

/* AI example, wide picture: it builds itself step by step the first time it scrolls into view (js/five-steps-anim.js).
   Scope, Organise, the handoff, Prove, Tune, the Centre of Excellence, then the loop draws back to the middle of
   step 1. The classes sit on the wrapper, so the full-screen viewer and print always show everything. */
.five-armed .stg { opacity: 0; transition: opacity 2s ease; }
.five-armed .stg.late { transition-delay: 1.5s; }
.five-armed.on-1 .s1, .five-armed.on-2 .s2, .five-armed.on-3 .s3, .five-armed.on-4 .s4,
.five-armed.on-5 .s5, .five-armed.on-6 .s6, .five-armed.on-7 .s7 { opacity: 1; }
.five-armed .stg.s7 { transition-delay: 6s; }
.five-armed.on-3 .d-handline { animation: hand-pulse 4s ease-out 1; }
@keyframes hand-pulse { 0%, 100% { stroke-width: 1.5; } 30% { stroke-width: 5; } }
.five-armed.on-3 .d-hand { animation: hand-glow 4s ease-out 1; }
@keyframes hand-glow { 30% { opacity: 1; font-size: 17px; } }
.loop-reveal { stroke-dasharray: 1 1; stroke-dashoffset: 0; }
.five-armed .loop-reveal { stroke-dashoffset: 1; }
.five-armed.on-7 .loop-reveal { stroke-dashoffset: 0; transition: stroke-dashoffset 6s ease-in-out; }
@media print { .five-armed .stg { opacity: 1; } .five-armed .loop-reveal { stroke-dashoffset: 0; } }

/* AI example on a phone: each step, then the handoff, the Centre of Excellence box and the loop line, fades up as
   you scroll to it, so the order reads as the picture does on a wide screen. The rail itself fills with the scroll. */
.vrail--steps.is-armed .vblock > :not(.varrow) { opacity: 0; transform: translateY(10px); transition: opacity 0.9s ease, transform 0.9s ease; }
.vrail--steps.is-armed .vblock.is-in > :not(.varrow) { opacity: 1; transform: none; }
.vrail--steps.is-armed .vblock.is-in > :nth-child(2) { transition-delay: 0.25s; }
.vrail--steps.is-armed .vblock.is-in > :nth-child(3) { transition-delay: 0.5s; }
.vrail--steps.is-armed .vblock.is-in > :nth-child(4) { transition-delay: 0.7s; }
.reveal-armed { opacity: 0; transform: translateY(10px); transition: opacity 0.9s ease, transform 0.9s ease; }
.reveal-armed.is-in { opacity: 1; transform: none; }
