/* ==========================================================================
   Interactive labs: DeepCS topology, Airlock gate
   Plus the /work and /about page furniture.
   ========================================================================== */

/* --- Work page shell --------------------------------------------------- */

.subnav {
  position: sticky;
  top: var(--nav-h);
  z-index: 60;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px) saturate(150%);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
}

.subnav__inner {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0.55rem var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
}

.subnav__inner::-webkit-scrollbar {
  display: none;
}

.subnav__link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.8rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
}

.subnav__link:hover {
  color: var(--text);
  background: var(--surface-2);
}

.subnav__link.is-active {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 32%, transparent);
  background: var(--wash-accent);
}

.subnav__link i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.75;
  flex: none;
}

/* System deep-dive header */
.sys {
  scroll-margin-top: calc(var(--nav-h) + var(--s-7));
}

.sys__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
  margin-bottom: var(--s-7);
}

@media (max-width: 880px) {
  .sys__head {
    grid-template-columns: 1fr;
  }
}

.sys__title-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-4);
}

.sys__title {
  font-size: clamp(1.9rem, 4.4vw, 2.7rem);
  letter-spacing: -0.038em;
}

.sys__oneline {
  font-size: var(--fs-lede);
  line-height: var(--lh-lede);
  color: var(--text-2);
  max-width: var(--measure-tight);
  margin-bottom: var(--s-5);
}

.sys__spec {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}

.sys__spec-row {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: 0.85rem;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

.sys__spec-row:last-child {
  border-bottom: 0;
}

.sys__spec-row dt {
  color: var(--faint);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-size: 0.68rem;
  padding-top: 0.15rem;
}

.sys__spec-row dd {
  margin: 0;
  color: var(--text-2);
  line-height: var(--lh-mono);
}

/* Honesty note: what a demo is and is not */
.note {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-2);
}

.note p {
  margin: 0;
  max-width: var(--measure);
}

.note svg {
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 0.3rem;
  color: var(--amber);
}

.note b {
  color: var(--text-2);
  font-weight: 600;
}

.note--inline {
  margin-top: 1rem;
}

/* Contents list for a single project, so it is obvious how many parts there
   are and where you currently are inside one. */
.sys__toc {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-5);
}

.sys__toc a {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--fs-sm);
  color: var(--text-2);
  transition: all 0.2s var(--ease);
}

.sys__toc a:hover {
  color: var(--text);
  border-color: var(--accent-deep);
  background: var(--surface-2);
}

.sys__toc a b {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--accent);
}

/* A lab is its own numbered part, with a rule above it so the boundary
   between parts is visible rather than implied by whitespace alone. */
.lab {
  margin-top: var(--s-8);
  padding-top: var(--s-7);
  border-top: 1px solid var(--border);
  scroll-margin-top: calc(var(--nav-h) + 4.5rem);
}

.lab__head {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}

.lab__num {
  flex: none;
  align-self: center;
  padding: 0.15rem 0.5rem;
  border-radius: 5px;
  background: var(--wash-accent);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.06em;
}

.lab__title {
  font-size: var(--fs-h3);
  line-height: var(--lh-h3);
  font-weight: 650;
  letter-spacing: -0.022em;
}

.lab__hint {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--faint);
}

.lab__intro {
  max-width: var(--measure);
  margin-bottom: var(--s-5);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-2);
}

/* Controls */
.ctl-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.ctl-row + .ctl-row {
  margin-top: 0.6rem;
}

.seg {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  gap: 3px;
}

.seg button {
  padding: 0.4rem 0.8rem;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--muted);
  transition: all 0.2s var(--ease);
  white-space: nowrap;
}

.seg button:hover {
  color: var(--text);
}

.seg button[aria-pressed="true"] {
  background: var(--surface-3);
  color: var(--accent);
  box-shadow: var(--shadow-1);
}

.seg--danger button[aria-pressed="true"][data-mode="racy"] {
  color: var(--red);
  background: var(--wash-red);
}

.ctl-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--faint);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 128px;
  height: 3px;
  border-radius: 3px;
  background: var(--border-strong);
  outline-offset: 6px;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  border: 0;
}

input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
}

/* ==========================================================================
   1. DeepCS topology
   ========================================================================== */

.topo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 316px);
  gap: 0;
}

@media (max-width: 1000px) {
  .topo {
    grid-template-columns: 1fr;
  }
}

.topo__stage {
  position: relative;
  min-width: 0;
  /* v1 and v2 have different aspect ratios, and the stage is as tall as the
     side column either way. Centring means the shorter diagram sits in the
     middle of the panel rather than leaving a dead band under it. */
  display: grid;
  align-content: center;
  background: radial-gradient(ellipse 80% 70% at 50% 40%, var(--surface-2), var(--bg-deep));
  border-right: 1px solid var(--border);
  overflow: hidden;
}

@media (max-width: 1000px) {
  .topo__stage {
    border-right: 0;
    border-bottom: 1px solid var(--border);
    overflow-x: hidden;
  }

  /* The stacked layout fits the screen, so nothing needs to scroll sideways. */
  .topo__svg--stacked {
    min-width: 0;
    max-width: 360px;
    margin-inline: auto;
  }
}

.topo__scroll-hint {
  display: none;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 1rem 0.55rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--faint);
}

.topo__scroll-hint svg {
  width: 13px;
  height: 13px;
  color: var(--accent);
  animation: nudge 1.8s var(--ease-in-out) infinite;
}

@keyframes nudge {
  0%,
  100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(4px);
  }
}

.topo__svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Node visuals */
.node {
  cursor: pointer;
}

.node__box {
  fill: var(--surface-2);
  stroke: var(--border-strong);
  stroke-width: 1.2;
  transition: fill 0.3s var(--ease), stroke 0.3s var(--ease), filter 0.3s var(--ease);
}

.node__label {
  fill: var(--text);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: -0.02em;
  pointer-events: none;
}

.node__sub {
  fill: var(--muted);
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.02em;
  pointer-events: none;
}

.node__idx {
  fill: var(--faint);
  font-family: var(--font-mono);
  font-size: 9px;
  pointer-events: none;
}

.node:hover .node__box,
.node.is-sel .node__box {
  fill: var(--surface-3);
  stroke: var(--accent);
}

.node.is-lit .node__box {
  stroke: var(--accent);
  fill: color-mix(in srgb, var(--accent) 14%, var(--surface-2));
  filter: drop-shadow(0 0 9px var(--glow-accent));
}

.node.is-dim {
  opacity: 0.28;
}

/* Data stores get an amber identity, jobs a violet one. */
.node--store .node__box {
  fill: var(--wash-amber);
  stroke: color-mix(in srgb, var(--amber) 42%, transparent);
}

.node--store.is-lit .node__box {
  stroke: var(--amber);
  filter: drop-shadow(0 0 9px rgba(251, 191, 36, 0.3));
  fill: color-mix(in srgb, var(--amber) 16%, var(--surface-2));
}

.node--job .node__box {
  stroke-dasharray: 5 4;
  stroke: color-mix(in srgb, var(--violet) 48%, transparent);
}

.node--job.is-lit .node__box {
  stroke: var(--violet);
  filter: drop-shadow(0 0 9px rgba(167, 139, 250, 0.3));
}

.node--client .node__box {
  fill: var(--surface);
  stroke-dasharray: 3 3;
}

/* Bought, not built: the services someone else runs. */
.node--ext .node__box {
  fill: color-mix(in srgb, var(--blue) 14%, transparent);
  stroke: color-mix(in srgb, var(--blue) 62%, transparent);
}

.node--ext.is-lit .node__box {
  stroke: var(--blue);
  filter: drop-shadow(0 0 9px rgba(121, 184, 255, 0.3));
  fill: color-mix(in srgb, var(--blue) 18%, var(--surface-2));
}

/* Instance stack marks behind a node = "×0–2 instances" */
.node__stack {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 0.65;
}

/* Edges */
.edge {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.3;
  transition: stroke 0.3s var(--ease), opacity 0.3s var(--ease), stroke-width 0.3s var(--ease);
}

.edge--internal {
  stroke-dasharray: 4 4;
  opacity: 0.75;
}

.edge--data {
  stroke: color-mix(in srgb, var(--amber) 30%, transparent);
}

.edge.is-lit {
  stroke: var(--accent);
  stroke-width: 2;
  opacity: 1;
}

.edge.is-dim {
  opacity: 0.12;
}

.zone {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
  stroke-dasharray: 3 5;
  rx: 14;
}

.zone__label {
  fill: var(--faint);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.packet {
  pointer-events: none;
}

/* Inspector */
.topo__side {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topo__scenarios {
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--border);
}

.topo__scenarios .ctl-label {
  display: block;
  margin-bottom: 0.55rem;
}

.scenario-btns {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.scenario-btn {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--text-2);
  text-align: left;
  transition: all 0.2s var(--ease);
}

.scenario-btn:hover {
  border-color: var(--accent-deep);
  color: var(--text);
}

.scenario-btn.is-running {
  border-color: var(--accent);
  background: var(--wash-accent);
  color: var(--accent);
}

.scenario-btn svg {
  width: 13px;
  height: 13px;
  flex: none;
  opacity: 0.8;
}

.topo__caption {
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
  min-height: 92px;
  background: var(--bg-deep);
}

.topo__caption-step {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.45rem;
}

.topo__caption-text {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-2);
  margin: 0;
}

.topo__inspect {
  flex: 1;
  padding: 0.9rem 1rem 1.1rem;
  min-height: 190px;
}

.topo__inspect h4 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.98rem;
  margin-bottom: 0.15rem;
}

.topo__inspect-kind {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 0.7rem;
  display: block;
}

.topo__inspect dl {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.topo__inspect dt {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.15rem;
}

.topo__inspect dd {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-2);
}

.topo__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.1rem;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--muted);
}

.topo__legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.topo__legend i {
  width: 14px;
  height: 0;
  border-top: 1.5px solid currentColor;
  flex: none;
}

.topo__legend i.dash {
  border-top-style: dashed;
}

.topo__legend i.box {
  width: 9px;
  height: 9px;
  border: 1.5px solid currentColor;
  border-radius: 2px;
}

/* ==========================================================================
   2. Airlock gate
   ========================================================================== */

.gate {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: 1px;
  background: var(--border);
}

@media (max-width: 900px) {
  .gate {
    grid-template-columns: 1fr;
  }
}

.gate__flow,
.gate__term {
  background: var(--surface);
  padding: 1.1rem;
  min-width: 0;
}

.gate__lanes {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-block: 0.9rem;
}

.lane {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  transition: all 0.3s var(--ease);
}

.lane.is-running {
  border-color: var(--accent);
  background: var(--wash-accent);
}

.lane.is-done {
  border-color: color-mix(in srgb, var(--green) 35%, transparent);
}

.lane.is-hit {
  border-color: var(--red);
  background: var(--wash-red);
}

.lane__icon {
  width: 26px;
  height: 26px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 6px;
  background: var(--surface-3);
  color: var(--muted);
  transition: color 0.3s var(--ease), background-color 0.3s var(--ease);
}

.lane__icon svg {
  width: 14px;
  height: 14px;
}

.lane.is-running .lane__icon {
  color: var(--accent);
}

.lane.is-done .lane__icon {
  color: var(--green);
}

.lane.is-hit .lane__icon {
  color: var(--red);
}

.lane__meta {
  min-width: 0;
  flex: 1;
}

.lane__name {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text);
  display: flex;
  gap: 0.45rem;
  align-items: baseline;
  flex-wrap: wrap;
}

.lane__name span {
  color: var(--faint);
  font-size: 0.7rem;
}

.lane__result {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: var(--lh-mono);
  color: var(--muted);
  min-height: 1.4em;
}

.lane.is-hit .lane__result {
  color: var(--red);
}

.lane.is-done .lane__result {
  color: var(--green);
}

.lane__spinner {
  width: 13px;
  height: 13px;
  flex: none;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  opacity: 0;
  animation: spin 0.7s linear infinite;
}

.lane.is-running .lane__spinner {
  opacity: 1;
}

.verdict {
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
  transition: all 0.35s var(--ease);
}

.verdict.is-block {
  border-color: var(--red);
  background: var(--wash-red);
  color: var(--red);
  font-weight: 600;
}

.verdict.is-safe {
  border-color: color-mix(in srgb, var(--green) 45%, transparent);
  background: color-mix(in srgb, var(--green) 9%, transparent);
  color: var(--green);
  font-weight: 600;
}

.tier {
  margin-top: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border-left: 2px solid var(--border-strong);
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: var(--lh-sm);
  max-width: var(--measure);
}

.tier b {
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: 0.75rem;
}

.term-window {
  height: 100%;
  min-height: 330px;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: #04060a;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  line-height: 1.65;
  color: #c9d4e2;
  white-space: pre-wrap;
  word-break: break-word;
  overflow-y: auto;
}

[data-theme="light"] .term-window {
  background: #0b0f16;
  color: #d5dee9;
}

.term-window .t-block {
  color: #f87171;
  font-weight: 600;
}

.term-window .t-safe {
  color: #4ade80;
  font-weight: 600;
}

.term-window .t-dim {
  color: #64748b;
}

.term-window .t-key {
  color: #fbbf24;
}

.term-window .t-prompt {
  color: #2dd4bf;
}

.term-cursor {
  display: inline-block;
  width: 7px;
  height: 1em;
  vertical-align: -0.15em;
  background: #2dd4bf;
  animation: blink 1.05s steps(2, start) infinite;
}

/* ==========================================================================
   3. About page
   ========================================================================== */

.about__hero {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 2.5rem);
  align-items: center;
}

@media (max-width: 640px) {
  .about__hero {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
}

.about__photo {
  position: relative;
  width: 168px;
  height: 168px;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
}

.about__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.about__photo::after {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 0 1px var(--wash-accent);
  pointer-events: none;
}

/* Timeline */
.timeline {
  position: relative;
  padding-left: 1.75rem;
}

.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 6px;
  bottom: 6px;
  width: 1.5px;
  background: linear-gradient(180deg, var(--accent), var(--border) 85%);
  opacity: 0.5;
}

.tl-item {
  position: relative;
  padding-bottom: var(--s-7);
}

.tl-item:last-child {
  padding-bottom: 0;
}

.tl-item::before {
  content: "";
  position: absolute;
  left: -1.75rem;
  top: 7px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border-strong);
  transition: all 0.4s var(--ease);
}

.tl-item.is-in::before {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--wash-accent);
}

.tl-item__when {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--faint);
  margin-bottom: 0.25rem;
}

.tl-item__what {
  font-size: 1.02rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  margin-bottom: 0.3rem;
}

.tl-item__what span {
  color: var(--accent);
  font-weight: 500;
}

.tl-item__detail {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-2);
  max-width: var(--measure);
}

/* Skills */
.skills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
}

.skillgrp {
  padding: 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}

.skillgrp h3 {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.8rem;
}

.skillgrp ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* Contact rows */
.contacts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 0.7rem;
}

.contact {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  transition: all 0.22s var(--ease);
}

.contact:hover {
  color: var(--text);
  border-color: var(--accent-deep);
  background: var(--surface-2);
  transform: translateY(-2px);
}

.contact svg {
  width: 17px;
  height: 17px;
  flex: none;
  color: var(--accent);
}

.contact span {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--faint);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.contact b {
  font-size: 0.9rem;
  font-weight: 550;
  word-break: break-all;
}

/* Figures.
   Explicit width/height attributes on every img so the browser reserves the
   right box before the file arrives and the page never jumps. */
.figure {
  margin: var(--s-6) 0 0;
}

.figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}

.figure figcaption {
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--muted);
  max-width: var(--measure);
}

.figure figcaption b {
  color: var(--text-2);
  font-weight: 600;
}

.figure--wide {
  max-width: 720px;
  margin-inline: auto;
}

.figure--wide figcaption {
  text-align: center;
  margin-inline: auto;
}

/* A certificate is a tall portrait document, so it gets a narrow column
   rather than the full content width. */
.figure--doc {
  max-width: 330px;
  margin-top: 0;
}

.figure--doc img {
  border-color: var(--border-strong);
}

.edu {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(1.5rem, 5vw, 4rem);
  align-items: start;
}

.edu .h1 {
  max-width: 14ch;
}

/* The bullet list is taller than the certificate, so a top-aligned figure
   leaves a long gap under it. Centring only the figure keeps the heading
   and bullets starting where they should. No effect once the grid stacks
   to one column, where each row is sized to its own content. */
.edu .figure--doc {
  align-self: center;
}

@media (max-width: 780px) {
  .edu {
    grid-template-columns: 1fr;
  }

  .figure--doc {
    max-width: 300px;
    margin-inline: auto;
  }
}

/* Prose blocks */
.prose {
  max-width: var(--measure);
}

.prose p {
  color: var(--text-2);
}

.prose strong {
  color: var(--text);
  font-weight: 600;
}

.prose h3 {
  margin: 2rem 0 0.75rem;
  font-size: 1.12rem;
}

.bullets {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  max-width: var(--measure);
}

.bullets li {
  position: relative;
  padding-left: 1.5rem;
  font-size: var(--fs-body);
  color: var(--text-2);
  line-height: var(--lh-body);
}

.bullets li::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.68em;
  width: 6px;
  height: 6px;
  border-radius: 1px;
  background: var(--accent);
  transform: rotate(45deg);
}

.bullets strong {
  color: var(--text);
  font-weight: 600;
}

/* Two-column feature split */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s-6) clamp(2rem, 5vw, 4rem);
}

.split > * > p:last-child {
  margin-bottom: 0;
}

/* Disclosure rows.
   Supporting rationale used to sit in open two-column walls of prose, which is
   most of what made the page feel heavy. It now collapses by default, so the
   page scans as a list of questions and expands only where the reader cares. */
.qa {
  display: grid;
  gap: var(--s-2);
  margin-top: var(--s-5);
  max-width: var(--measure-wide);
}

.qa__item {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}

.qa__item[open] {
  border-color: var(--border-strong);
  background: var(--surface-2);
}

.qa__sum {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  transition: background-color 0.2s var(--ease);
}

.qa__sum::-webkit-details-marker {
  display: none;
}

.qa__sum:hover {
  background: var(--surface-2);
}

/* A bare chevron does not read as "expandable", so the trigger says so in
   words and the whole row behaves like a control. */
.qa__toggle {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}

.qa__toggle::after {
  content: "Show";
}

.qa__item[open] .qa__toggle::after {
  content: "Hide";
}

.qa__sum svg {
  flex: none;
  width: 13px;
  height: 13px;
  color: currentColor;
  transition: transform 0.25s var(--ease);
}

.qa__item[open] .qa__toggle svg {
  transform: rotate(180deg);
}

.qa__body {
  padding: 0 var(--s-4) var(--s-4);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-2);
}

.qa__body p {
  max-width: var(--measure);
  margin: 0;
}

.qa__body p + p {
  margin-top: var(--s-3);
}

/* ADR list */
.adr {
  display: grid;
  gap: var(--s-2);
  max-width: var(--measure-wide);
}

.adr__item {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}

.adr__item[open] {
  border-color: var(--border-strong);
}

.adr__sum {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.85rem 1rem;
  cursor: pointer;
  list-style: none;
  font-size: 0.95rem;
  font-weight: 550;
  letter-spacing: -0.015em;
  transition: background-color 0.2s var(--ease);
}

.adr__sum::-webkit-details-marker {
  display: none;
}

.adr__sum:hover {
  background: var(--surface-2);
}

.adr__num {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  padding: 0.15rem 0.45rem;
  border-radius: 4px;
  background: var(--wash-accent);
  color: var(--accent);
  flex: none;
}

.adr__toggle {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}

.adr__toggle::after {
  content: "Show";
}

.adr__item[open] .adr__toggle::after {
  content: "Hide";
}

.adr__caret {
  flex: none;
  width: 13px;
  height: 13px;
  color: currentColor;
  transition: transform 0.25s var(--ease);
}

.adr__item[open] .adr__caret {
  transform: rotate(180deg);
}

.adr__body {
  padding: var(--s-4) var(--s-5) var(--s-5);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-2);
  border-top: 1px solid var(--border);
}

.adr__body p {
  max-width: var(--measure);
  margin: 0;
}

.adr__body p + p {
  margin-top: var(--s-4);
}

.adr__body b {
  color: var(--text);
}

.adr__tradeoff {
  display: block;
  margin-top: 0.7rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--amber);
  font-size: 0.85rem;
  color: var(--muted);
}

/* The invisible textarea that gives phones something to focus, so the on-screen
   keyboard appears. It must be focusable and non-zero-sized, not display:none. */
.editor__keyer {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  opacity: 0;
  resize: none;
  overflow: hidden;
  /* 16px stops iOS zooming the page when the field takes focus. */
  font-size: 16px;
}

.editor.is-focused {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--wash-accent);
}

/* Marks a panel as something to use rather than read. Without it, several
   people read the demos as static diagrams and never touched them. */
.panel__try {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: none;
  padding: 0.15rem 0.5rem;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 999px;
  background: var(--wash-accent);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.panel__try svg {
  width: 12px;
  height: 12px;
}

/* On a phone the two replicas stack, so they have to be short enough that both
   are on screen together. Seeing them agree is the entire point of the demo. */
@media (max-width: 900px) {
  .crdt__pane {
    padding: var(--s-3) var(--s-4);
  }

  .editor {
    min-height: 84px;
    font-size: 0.8rem;
    line-height: 1.6;
  }

  .crdt__pane-head {
    font-size: var(--fs-micro);
    gap: 0.4rem;
  }

  .crdt__wire {
    padding: 0.4rem 0.75rem;
  }

  .crdt__wire-label {
    font-size: 0.6rem;
  }

  .crdt__status {
    font-size: var(--fs-micro);
    gap: 0.35rem 0.7rem;
    padding: var(--s-3) var(--s-4);
  }
}

/* Playback controls for the request walkthrough. The captions carry real
   detail, so it has to be possible to stop and go back. */
.topo__controls {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
}

.topo__ctrl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 32px;
  padding: 0 0.6rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: all 0.2s var(--ease);
}

.topo__ctrl:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--accent-deep);
  background: var(--surface-3);
}

.topo__ctrl:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.topo__ctrl--play {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: var(--wash-accent);
  padding-inline: 0.75rem;
}

.topo__ctrl .topo__icon-pause {
  display: none;
}

.topo__ctrl.is-playing .topo__icon-pause {
  display: block;
}

.topo__ctrl.is-playing .topo__icon-play {
  display: none;
}

/* Tells you the terminal is waiting on you, rather than being broken. */
.gate__term {
  position: relative;
}

.gate__hint {
  position: absolute;
  inset: auto var(--s-5) var(--s-5) var(--s-5);
  margin: 0;
  max-width: none;
  padding: var(--s-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--muted);
  transition: opacity 0.3s var(--ease);
}

.gate__hint b {
  color: var(--text-2);
}

.gate__hint.is-hidden {
  opacity: 0;
  pointer-events: none;
}

/* A display value beats the hidden attribute, so say it outright. */
.topo__controls[hidden] {
  display: none;
}

.topo__inspect-empty {
  margin: 0;
  max-width: none;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--muted);
}

/* ---- Mobile: put the controls where the diagram is ---------------------- */
@media (max-width: 1000px) {
  .topo__side {
    display: flex;
    flex-direction: column;
  }

  /* Caption and playback controls sit directly under the diagram, so the
     step can be read and paused without scrolling past everything else. */
  .topo__caption {
    order: 1;
  }

  .topo__scenarios {
    order: 2;
  }

  .topo__inspect {
    order: 3;
    min-height: 0;
  }

  .topo__caption {
    position: sticky;
    top: calc(var(--nav-h) + 44px);
    z-index: 5;
    background: color-mix(in srgb, var(--bg-deep) 94%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }

  .topo__controls {
    gap: var(--s-1);
  }

  .topo__ctrl {
    min-height: 36px;
  }
}

/* ---- Mobile: keep the Airlock terminal from running off the page -------- */
@media (max-width: 900px) {
  .term-window {
    min-height: 0;
    max-height: 300px;
    overflow-y: auto;
    font-size: 0.72rem;
  }

  .gate__hint {
    position: static;
    inset: auto;
    margin-top: var(--s-3);
  }

  .gate__flow,
  .gate__term {
    padding: var(--s-4);
  }

  .lane {
    padding: var(--s-3);
  }

  .tier {
    font-size: var(--fs-xs);
  }
}

@media (max-width: 900px) {
  /* Four lanes were 134px each because the text wrapped three times. */
  .lane {
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
  }

  .lane__icon {
    width: 22px;
    height: 22px;
  }

  .lane__name {
    font-size: 0.78rem;
  }

  .lane__result {
    font-size: 0.72rem;
    line-height: 1.5;
  }

  .gate__lanes {
    gap: var(--s-2);
  }

  .term-window {
    max-height: 240px;
  }
}

/* ============================================================
   TOUCH TARGETS, LAB CONTROLS
   Same reasoning as the block at the end of site.css. These are the
   controls the demos are driven from, so they are the ones a thumb
   has to hit. Desktop keeps its denser sizing.
   ============================================================ */
@media (pointer: coarse) {
  /* iOS Safari zooms the whole page in when a focused field computes
     under 16px, and never zooms back out. 16px keeps the search usable. */
  .ir__input {
    font-size: 16px;
  }

  .ir__chip {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: 0.9rem;
  }

  .topo__ctrl {
    min-height: 44px;
    min-width: 44px;
  }

  .scenario-btn {
    min-height: 44px;
  }

  .subnav__link {
    min-height: 44px;
  }
}
