/* Stefan Schultz · portfolio
   Direction "Modeler": the page reads like a BPMN diagram. A sequence-flow rail runs down the left,
   a start event at the top, one intermediate catch event per chapter, an end event at the footer,
   and the flow fills as you scroll. Plain CSS, two themes, three self-hosted fonts.
   Fonts live in /fonts, images in /img. Edit freely. */

/* ---------- fonts ---------- */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/fonts/bricolage-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/fonts/bricolage-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("/fonts/sourcesans3-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Sans 3";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("/fonts/sourcesans3-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/fonts/jetbrainsmono-latin.woff2") format("woff2");
}

/* ---------- tokens ---------- */
:root {
  color-scheme: light;
  --bg: #ffffff;
  --bg-2: #f5f6f5;
  --surface: #ffffff;
  --ink: #0f1417;
  --ink-2: #343c42;
  --muted: #66727a;
  --line: #e3e6e8;
  --line-2: #cbd2d6;
  --accent: #0e7c73;
  --accent-hover: #0a5f58;
  --accent-soft: #dcefec;
  --accent-ink: #0b5f58;
  --event: #a8730a;
  --on-accent: #ffffff;
  /* gold for a highlighted talk: a mid tone for the ring, a bright one and a pale sheen for the gradient */
  --gold: #c08a12;
  --gold-bright: #eec350;
  --gold-sheen: #fff4d0;
  --gold-ink: #3d2a00;
  --dot: rgba(15, 20, 23, 0.10);
  --shadow: 0 1px 2px rgba(15, 20, 23, 0.04), 0 12px 32px -20px rgba(15, 20, 23, 0.25);
  --chapter-shadow: 0 -28px 60px -44px rgba(0, 0, 0, 0.45);

  --font-display: "Bricolage Grotesque", "Helvetica Neue", Arial, sans-serif;
  --font-sans: "Source Sans 3", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --header-h: 64px;
  --h2-size: clamp(2rem, 4.2vw, 3.2rem);
  --wrap: 1160px;
  --gutter: clamp(1rem, 4vw, 2.5rem);
  --rail: 0px;
  --marker-size: 35px; /* the flow's event rings, border-box, so half of this is a ring's centre */
  --flow-glow: 0 0 14px 6px color-mix(in srgb, var(--accent) 35%, transparent); /* soft halo on the reached event, one definition so all three markers agree */
  --radius: 12px;
  --radius-sm: 8px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0e1316;
    --bg-2: #12181c;
    --surface: #151c21;
    --ink: #e6ebee;
    --ink-2: #c4ccd2;
    --muted: #8fa0a8;
    --line: #263239;
    --line-2: #34434c;
    --accent: #3fd3c4;
    --accent-hover: #7ee8dc;
    --accent-soft: #12332f;
    --accent-ink: #8fe3da;
    --event: #f2b950;
    --on-accent: #0e1316;
    --gold: #e0aa3c;
    --gold-bright: #ffd782;
    --gold-sheen: #fff8e4;
    --gold-ink: #2a1c00;
    --dot: rgba(230, 235, 238, 0.10);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 12px 32px -20px rgba(0, 0, 0, 0.7);
    --chapter-shadow: 0 -28px 60px -40px rgba(0, 0, 0, 0.95);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0e1316;
  --bg-2: #12181c;
  --surface: #151c21;
  --ink: #e6ebee;
  --ink-2: #c4ccd2;
  --muted: #8fa0a8;
  --line: #263239;
  --line-2: #34434c;
  --accent: #3fd3c4;
  --accent-hover: #7ee8dc;
  --accent-soft: #12332f;
  --accent-ink: #8fe3da;
  --event: #f2b950;
  --on-accent: #0e1316;
  --gold: #e0aa3c;
  --gold-bright: #ffd782;
  --gold-sheen: #fff8e4;
  --gold-ink: #2a1c00;
  --dot: rgba(230, 235, 238, 0.10);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 12px 32px -20px rgba(0, 0, 0, 0.7);
  --chapter-shadow: 0 -28px 60px -40px rgba(0, 0, 0, 0.95);
}
@media (min-width: 1024px) { :root { --rail: 72px; } }
@media (max-width: 760px) { :root { --header-h: 72px; } }

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-padding-top: calc(var(--header-h) + 1px); scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  overflow-x: clip; /* the talks strip spans to the viewport edge with 100vw margins; classic scrollbars must not add sideways scroll */
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 1.125rem;
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0; line-height: 1.1; text-wrap: balance; font-family: var(--font-display); font-weight: 700; letter-spacing: -0.025em; }
h1 { font-size: clamp(3rem, 8.5vw, 7rem); font-weight: 800; line-height: 0.95; letter-spacing: -0.04em; }
h2 { font-size: var(--h2-size); }
h3 { font-size: 1.25rem; letter-spacing: -0.015em; }
p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }
a { color: var(--accent-ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.14em; text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); }
a:hover { color: var(--accent-hover); text-decoration-color: currentColor; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
img, svg { display: block; max-width: 100%; }
ul, ol { margin: 0; padding: 0; }
time { font-variant-numeric: tabular-nums; }
::selection { background: var(--accent-soft); color: var(--ink); }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: calc(var(--gutter) + var(--rail)) var(--gutter); position: relative; }
.skip { position: absolute; left: 1rem; top: -4rem; background: var(--accent); color: var(--on-accent); padding: 0.6rem 1rem; border-radius: var(--radius-sm); z-index: 100; text-decoration: none; font-weight: 600; }
.skip:focus { top: 1rem; }

.kicker { font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.06em; color: var(--accent); }
.mono { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); }
.muted { color: var(--muted); }
.lead { font-size: clamp(1.25rem, 1.8vw, 1.5rem); line-height: 1.5; color: var(--ink-2); max-width: 34em; font-weight: 400; }

.chip {
  display: inline-flex; align-items: center; gap: 0.35em;
  font-family: var(--font-mono); font-size: 0.76rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--accent-ink); background: var(--accent-soft);
  padding: 0.22rem 0.5rem; border-radius: 4px; white-space: nowrap;
}
.chip--plain { background: transparent; border: 1px solid var(--line-2); color: var(--muted); }
.chip--event { background: color-mix(in srgb, var(--event) 18%, transparent); color: color-mix(in srgb, var(--event) 75%, var(--ink)); }

.icon { width: 1em; height: 1em; fill: currentColor; flex: none; }
.icon-ext { fill: none; } /* a stroke-drawn glyph, unlike the filled logo icons .icon otherwise assumes */

.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-weight: 600; font-size: 0.95rem; text-decoration: none;
  padding: 0.7rem 1.05rem; border-radius: 6px; border: 1px solid var(--line-2);
  color: var(--ink); background: var(--surface);
  transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.15s ease, color 0.15s ease;
}
.btn:hover { border-color: var(--accent); color: var(--accent-ink); }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); }
.btn .icon { font-size: 1.05rem; }

/* ---------- header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 84%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.site-header .wrap { display: flex; align-items: center; gap: 1rem; min-height: 64px; padding-inline-start: var(--gutter); }
.brand { display: inline-flex; align-items: center; gap: 0.6rem; text-decoration: none; color: var(--ink); font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; font-size: 1.05rem; }
.brand .mark { width: 26px; height: 26px; }
:root[data-theme="dark"] .brand .mark, :root[data-theme="dark"] .notfound .mark { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand .mark, :root:not([data-theme="light"]) .notfound .mark { filter: invert(1); }
}
.brand:hover { color: var(--accent-ink); }
.site-nav { margin-inline-start: auto; }
.site-nav ul { display: flex; gap: clamp(0.5rem, 1.5vw, 1.25rem); list-style: none; }
.site-nav a { text-decoration: none; color: var(--ink-2); font-family: var(--font-mono); font-size: 0.875rem; padding: 0.7rem 0.1rem; border-bottom: 2px solid transparent; }
.site-nav a:hover, .site-nav a[aria-current="true"] { color: var(--ink); border-bottom-color: var(--accent); }
.controls { display: flex; align-items: center; gap: 0.5rem; }
.lang-switch {
  font-family: var(--font-mono); font-size: 0.78rem; text-decoration: none; letter-spacing: 0.05em;
  color: var(--ink-2); border: 1px solid var(--line-2); padding: 0.3rem 0.55rem; border-radius: 4px;
}
.lang-switch:hover { border-color: var(--accent); color: var(--accent-ink); }
.theme-toggle {
  appearance: none; border: 1px solid var(--line-2); background: transparent; color: var(--ink-2);
  width: 44px; height: 44px; border-radius: 4px; display: inline-grid; place-items: center; cursor: pointer;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent-ink); }
.theme-toggle .icon { width: 17px; height: 17px; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: none; }
}
.menu-toggle { display: none; }
.lang-switch { min-width: 44px; min-height: 44px; display: inline-grid; place-items: center; }
@media (max-width: 760px) {
  .site-header .wrap { flex-wrap: wrap; gap: .375rem; min-height: 72px; padding-block: .5rem; }
  .brand { font-size: 1rem; }
  .nav-ready .menu-toggle { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; margin-inline-start: auto; padding: .5rem .65rem; border: 1px solid var(--line-2); border-radius: 4px; background: var(--surface); color: var(--ink); font: inherit; font-size: .875rem; cursor: pointer; }
  .menu-toggle[aria-expanded="true"] { border-color: var(--accent); background: var(--accent-soft); }
  .site-nav { order: 3; flex-basis: 100%; margin: 0; }
  .site-nav ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .25rem .75rem; border-top: 1px solid var(--line); padding-top: .5rem; }
  .site-nav a { display: flex; align-items: center; min-height: 44px; font-size: .875rem; padding: .5rem; }
  .nav-ready .site-nav:has(a[href^="#"]):not(.is-open) { display: none; }
  .controls { margin-inline-start: auto; gap: .35rem; }
  .nav-ready .menu-toggle + .controls { margin-inline-start: 0; }
}
@media (max-width: 359px) { .brand-name { max-width: 5.5rem; line-height: 1.1; } }

/* ---------- the sequence flow rail: start event at the hero, one intermediate catch event per chapter, end event after the last chapter ---------- */
main.flow, .flow-track { position: relative; }
.flow-end { display: none; }
.rail { display: none; }
@media (min-width: 1024px) {
  .rail { display: block; position: absolute; top: var(--rail-start, 5rem); height: var(--rail-length, 0px); z-index: 1; left: calc(max(0px, (100% - var(--wrap)) / 2) + var(--gutter) + 15px); width: 2px; background: var(--line-2); pointer-events: none; }
  .rail-fill { position: absolute; left: 0; top: 0; width: 100%; height: calc(var(--rail-progress, 0) * 100%); background: var(--accent); }
  /* markers sit next to the content they belong to: the first line of the hero heading, each chapter heading, the end of the last chapter */
  .hero[data-marker="start"]::before, .chapter[data-marker="catch"] .section-head::before, .flow-end {
    content: ""; position: absolute; z-index: 2; left: calc(max(0px, (100% - var(--wrap)) / 2) + var(--gutter)); width: var(--marker-size); height: var(--marker-size); box-sizing: border-box;
    border-radius: 50%; border: 2px solid var(--line-2); background: var(--bg); pointer-events: none;
  }
  .hero[data-marker="start"]::before { top: calc(var(--rail-start, 5rem) - var(--marker-size) / 2); border-width: 2px; }
  /* the catch event is anchored to the heading itself: the .wrap content edge sits var(--rail) right of the rail column,
     and the circle is centred on the first line of the h2 (line-height 1.1) */
  .section-head { position: relative; }
  .chapter[data-marker="catch"] .section-head::before { left: calc(-1 * var(--rail)); top: calc(var(--h2-size) * 0.55 - var(--marker-size) / 2); box-shadow: inset 0 0 0 3px var(--bg), inset 0 0 0 5px var(--line-2); }
  .flow-end { display: block; top: calc(clamp(2.5rem, 5vw, 4rem) + clamp(1.8rem, 3vw, 2.5rem) * .55 - var(--marker-size) / 2); border-width: 5px; background: var(--accent-soft); }
  .hero.was-active::before { border-color: var(--accent); }
  .hero.is-flow-active::before { box-shadow: var(--flow-glow); }
  .chapter.was-active .section-head::before { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--bg), inset 0 0 0 5px var(--accent); }
  .chapter.is-flow-active .section-head::before { box-shadow: inset 0 0 0 3px var(--bg), inset 0 0 0 5px var(--accent), var(--flow-glow); }
  main.flow.is-end .flow-end { border-color: var(--accent); box-shadow: var(--flow-glow); }
  /* the script sets rail-off when a piece of the rail's markup is missing: better no decoration than half of it */
  main.flow.rail-off .rail, main.flow.rail-off .flow-end,
  main.flow.rail-off .hero[data-marker="start"]::before,
  main.flow.rail-off .chapter[data-marker="catch"] .section-head::before { display: none; }
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rail-fill { transition: none; }
  .to-top { transition: none; }
  *, *::before, *::after { animation: none !important; }
}

/* ---------- hero (start event) ---------- */
.hero { padding-block: clamp(2.75rem, 6vw, 5rem) clamp(2.5rem, 5vw, 4rem); position: relative; }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr); gap: clamp(2rem, 6vw, 5rem); align-items: center; }
.hero-copy > * + * { margin-top: 1.5rem; }
.hero .kicker { display: block; }
.hero .lead { margin-top: 1.5rem; max-width: 38ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.75rem; }
.social-link { display: inline-flex; align-items: center; gap: .45rem; min-height: 44px; padding: .25rem .4rem; font-size: .95rem; color: var(--ink-2); text-decoration-color: var(--line-2); }
.hero .link-row { gap: .25rem .65rem; }
.find-me .kicker { margin-bottom: .2rem; }
.find-me { margin-top: 2.25rem; }
.find-me .kicker { display: block; margin-bottom: 0.75rem; color: var(--muted); }
.link-row { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; }
.portrait-wrap { display: grid; place-items: center; margin: 0; }
.portrait {
  position: relative; width: min(340px, 100%); aspect-ratio: 1; border-radius: 50%;
  padding: 12px; border: 2px solid var(--accent); background: var(--bg);
}
.portrait::before { content: ""; position: absolute; inset: -16px; border: 2px solid var(--accent); border-radius: 50%; }
.portrait picture { display: block; }
.portrait img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; border-radius: 50%; object-fit: cover; filter: grayscale(1) contrast(1.04); }
@media (max-width: 860px) {
  .hero-grid { grid-template-columns: 1fr; }
  .portrait-wrap { justify-items: start; }
  .portrait { width: min(220px, 100%); margin-inline-start: 20px; }
}

/* ---------- facts ---------- */
.facts { border-block: 1px solid var(--line); background: var(--bg-2); }
.facts ul { list-style: none; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); } /* one column per fact */
.facts li { padding: 1.75rem 1.25rem 1.75rem 0; border-inline-start: 1px solid var(--line); padding-inline-start: 1.25rem; }
.facts li:first-child { border-inline-start: 0; padding-inline-start: 0; }
.facts .value { font-family: var(--font-display); font-size: clamp(2rem, 3.6vw, 3rem); font-weight: 800; line-height: 1; letter-spacing: -0.04em; color: var(--ink); display: block; }
.facts .label { display: block; margin-top: 0.5rem; font-size: 0.95rem; color: var(--muted); }

/* tech blog: the two tracks, side by side */
.tracks { margin-top: 2rem; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem clamp(1.5rem, 4vw, 3rem); }
@media (max-width: 760px) { .tracks { grid-template-columns: 1fr; } }
.track { display: grid; gap: 0.5rem; justify-items: start; align-content: start; padding-top: 0.9rem; border-top: 2px solid var(--line-2); }
.track h3 { font-size: 1.3rem; }
.track p { color: var(--ink-2); font-size: 1rem; max-width: 46ch; }
.all-posts { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; }
.all-posts .tech-note { margin: 0; }
@media (max-width: 760px) {
  .facts ul { grid-auto-flow: row; grid-template-columns: 1fr 1fr; }
  .facts li:nth-child(3) { border-inline-start: 0; padding-inline-start: 0; }
  .facts li:nth-child(n + 3) { border-top: 1px solid var(--line); padding-top: 1.25rem; }
  .facts li:last-child:nth-child(odd) { grid-column: 1 / -1; } /* an odd last fact takes the full row */
  .facts li { padding-block: 1.25rem; }
}

/* ---------- chapters: consistent statements followed by readable content ---------- */
.chapter { position: relative; }
.beat {
  position: relative; z-index: 0;
  display: grid; align-items: center; padding-block: clamp(1.5rem, 3vw, 2.25rem);
  background-color: var(--bg); background-image: radial-gradient(var(--dot) 1px, transparent 1px); background-size: 13px 13px;
  border-top: 1px solid var(--line); /* closes the band: the chapter body below draws the matching line */
}
.facts + .chapter .beat { border-top-width: 0; } /* the facts strip already draws that line */
.beat-inner { width: 100%; display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); align-items: start;  }
.beat .kicker { color: var(--muted); grid-column: 1 / -1; }
@media (max-width: 900px) { .beat-inner { grid-template-columns: 1fr; align-items: start; } }
.statement-text { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.8rem, 3.2vw, 2.8rem); line-height: 1.05; letter-spacing: -0.035em; width: 100%; max-width: 30ch; color: var(--ink); margin: 0; text-wrap: balance; }
.statement-text em { font-style: normal; color: var(--accent-ink); }
.beat-sub { font-size: clamp(1.15rem, 1.5vw, 1.32rem); line-height: 1.5; color: var(--ink-2); max-width: 60ch; margin: 0; padding-bottom: 0; text-wrap: pretty; }
.chapter-body { position: relative; background: var(--bg); border-top: 1px solid var(--line); padding-block: clamp(3.5rem, 7vw, 6rem) clamp(2rem, 4vw, 3.5rem); } /* more room above the heading, so its catch event lights up a little later after the beat */
@media (max-width: 760px) { .beat { padding-block: 1.5rem; } }
@media (prefers-reduced-motion: reduce) {
  .beat { position: static; }
  .beat-inner { opacity: 1; transform: none; }
}


/* ---------- sections (tasks) ---------- */
.section-head { margin-bottom: clamp(1.75rem, 3.5vw, 2.5rem); }

.prose { max-width: 66ch; }
.prose p { color: var(--ink-2); }
.prose p + p { margin-top: 1rem; }

/* about layout */
.about-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); }
@media (max-width: 860px) { .about-grid { grid-template-columns: 1fr; } }
.career { list-style: none; display: grid; gap: 0; margin-top: 0.75rem; position: relative; }
.career::before { content: ""; position: absolute; left: 8px; top: 12px; bottom: 12px; width: 2px; background: var(--line-2); }
.career li { position: relative; padding: 0.25rem 0 1.4rem 2rem; }
.career li::before { content: ""; position: absolute; left: 3px; top: 0.55rem; width: 12px; height: 12px; border-radius: 50%; background: var(--bg); border: 2px solid var(--accent); }
.career li:last-child { padding-bottom: 0; }
.career .period { display: block; margin-bottom: 0.2rem; }
.career .role { font-weight: 700; font-family: var(--font-display); letter-spacing: -0.01em; font-size: 1.1rem; }
.career .org { color: var(--muted); font-size: 0.95rem; margin-top: 0.1rem; }
.career .note { font-size: 0.95rem; color: var(--ink-2); margin-top: 0.4rem; }
.career a { color: inherit; }

/* current client work: one tile each, one row */
.work-grid { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 1.25rem; align-items: stretch; }
.work-tile { background: var(--surface); border: 1px solid var(--line); border-top: 3px solid var(--accent); border-radius: var(--radius); padding: 1.1rem 1.25rem 1.25rem; display: flex; flex-direction: column; gap: 0.5rem; box-shadow: var(--shadow); transition: transform 0.25s var(--ease), border-color 0.25s ease; }
.work-tile:hover { border-color: var(--line-2); }
.work-meta { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.work-tile h4 { font-size: 1.1rem; font-weight: 700; margin: 0; }
.work-tile p { margin: 0; color: var(--ink-2); font-size: 0.92rem; hyphens: auto; overflow-wrap: break-word; }

/* compact lists: earlier work, further series, further repositories. A period column, then title and one paragraph. */
.compact-list { list-style: none; display: grid; gap: 0; border-top: 1px solid var(--line); }
.compact-list > li { display: grid; grid-template-columns: 9.5rem minmax(0, 1fr); gap: 0.25rem 1.5rem; padding: 0.75rem 0; border-bottom: 1px solid var(--line); align-items: baseline; }
/* on wide screens the lists flow in two columns, chronological left to right */
@media (min-width: 1024px) {
  .compact-list { grid-template-columns: 1fr; }
  .compact-list > li { grid-template-columns: 7.5rem minmax(0, 1fr); gap: 0.2rem 1.1rem; }
}
.compact-list .period { padding-top: 0.2rem; }
.compact-list h4 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; display: inline; }
.compact-list h4 a { color: var(--ink); text-decoration: none; }
.compact-list h4 a:hover { color: var(--accent-ink); text-decoration: underline; }
.compact-list p { margin: 0.25rem 0 0; color: var(--ink-2); font-size: 0.95rem; max-width: 72ch; hyphens: auto; overflow-wrap: break-word; }
.compact-list .line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.75rem; }
.compact-list .foot { font-size: 0.88rem; margin-top: 0.3rem; }
@media (max-width: 600px) {
  .compact-list > li { grid-template-columns: 1fr; gap: 0.1rem; }
  .compact-list .period { padding-top: 0; }
}
.other-certs { list-style: none; display: grid; gap: 0.5rem; font-size: 0.97rem; color: var(--ink-2); }
.other-certs li { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr); gap: 0.75rem; align-items: baseline; }

.subhead { display: flex; align-items: baseline; gap: 1rem; margin-top: clamp(2rem, 4vw, 3rem); margin-bottom: 1rem; }
.subhead h3 { font-size: 1.5rem; }
.subhead .rule { flex: 1; height: 1px; background: var(--line); }
.subhead--minor { margin-top: clamp(1.5rem, 3vw, 2.25rem); margin-bottom: 0.75rem; } /* the list below draws its own top rule, so it needs air */
.subhead--minor h3 { font-size: 1.05rem; font-family: var(--font-sans); font-weight: 700; letter-spacing: 0; color: var(--ink-2); }
.subhead--minor .rule { display: none; }

/* tools, grouped */
.tool-groups { display: grid; gap: 0.9rem; }
@media (min-width: 1024px) { .tool-groups { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 2.5rem; } }
.tool-group { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: 0.5rem 1.1rem; align-items: start; }
.tool-group .kicker { color: var(--muted); padding-top: 0.55rem; }
@media (max-width: 600px) { .tool-group { grid-template-columns: 1fr; gap: 0.35rem; } .tool-group .kicker { padding-top: 0; } }
.tech { list-style: none; display: flex; flex-wrap: wrap; gap: 0.45rem; }
.tech li {
  display: inline-flex; align-items: center; gap: 0.55rem; white-space: nowrap;
  padding: 0.45rem 0.7rem; background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  font-size: 0.9rem; color: var(--ink-2);
}
.tech .icon { width: 18px; height: 18px; color: var(--muted); transition: color 0.15s ease; }
.tech li:hover .icon { color: var(--brand, var(--accent)); }
.tech-note { margin-top: 0.85rem; font-size: 0.85rem; color: var(--muted); }

/* ---------- tech blog: compact series tiles, equal size, rows aligned across the grid ---------- */
.series-grid { list-style: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; align-items: stretch; }
@media (max-width: 960px) { .series-grid { grid-template-columns: 1fr; } }
.series-tile {
  display: grid; grid-template-rows: subgrid; grid-row: span 5; row-gap: 0.6rem; align-content: start;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.25rem 1.4rem;
  box-shadow: var(--shadow); transition: transform 0.25s var(--ease), border-color 0.25s ease;
}
@supports not (grid-template-rows: subgrid) {
  .series-tile { display: flex; flex-direction: column; gap: 0.6rem; }
  .series-tile .series-link { margin-top: auto; }
}
.series-tile:hover, .series-tile:focus-within { border-color: var(--accent); }
.series-meta { display: grid; gap: 0.5rem; justify-items: start; }
.series-tile .count { font-family: var(--font-display); font-weight: 800; font-size: clamp(1.8rem, 2.6vw, 2.2rem); line-height: 1; letter-spacing: -0.04em; color: var(--accent-ink); }
.series-tile .count small { font-family: var(--font-mono); font-size: 0.76rem; font-weight: 400; letter-spacing: 0.05em; color: var(--muted); margin-inline-start: 0.4rem; }
.series-tile h4 { font-size: 1.25rem; align-self: start; }
.series-tile h4 a { color: var(--ink); text-decoration: none; }
.series-tile h4 a:hover { color: var(--accent-ink); }
.series-tile .tagline { font-size: 1rem; color: var(--ink-2); margin: 0; align-self: start; }
.series-tile .series-link { margin: 0.2rem 0 0; font-size: 0.92rem; font-weight: 600; align-self: end; }
.all-posts { margin: clamp(1.75rem, 3vw, 2.5rem) 0 0; }
.elsewhere { margin-top: 1.5rem; display: grid; gap: 0.75rem; }
.elsewhere li { display: flex; gap: 0.75rem; align-items: baseline; list-style: none; flex-wrap: wrap; }
.elsewhere .meta { color: var(--muted); font-size: 0.92rem; }

/* ---------- talks (gateway): a horizontal sequence flow, one card per talk ----------
   The strip starts at the content column and bleeds to the right edge of the viewport.
   Dates sit as event markers on a line above the cards, once per month group; the
   upcoming talk is a waiting catch event (double ring). Arrows, the progress fill and
   the edge fades come from main.js; without JavaScript the strip scrolls natively. */
.talks-panel { --card-w: min(345px, 80vw); --card-gap: 1.25rem; --card-pad: 1.15rem; }
.section-head--row { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.panel-nav { display: flex; gap: 0.5rem; margin-bottom: 0.35rem; }
.pbtn { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: border-color 0.15s ease, color 0.15s ease; }
.pbtn svg { width: 16px; height: 16px; }
.pbtn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-ink); }
.pbtn:disabled { opacity: 0.35; cursor: default; }
/* The left fade lives in a pad zone LEFT of the snap position: a card the arrows snap to starts after the
   fade, only the tail of the previous card fades out under it. */
.tscroll { --edge-fade: 48px; display: flex; align-items: flex-start; gap: var(--card-gap); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none;
  margin-inline-start: calc(-1 * var(--edge-fade)); padding-inline-start: var(--edge-fade); scroll-padding-inline-start: var(--edge-fade);
  margin-inline-end: calc(min(0px, (var(--wrap) - 100vw) / 2) - var(--gutter));
  padding-inline-end: calc(max(0px, (100vw - var(--wrap)) / 2) + var(--gutter));
  padding-block-end: 10px; /* room for the cards' shadows, which would otherwise cut off on the tallest card */ }
.tscroll::-webkit-scrollbar { display: none; }
.tscroll.fade-r { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 72px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 72px), transparent); }
.tscroll.fade-l { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--edge-fade)); mask-image: linear-gradient(90deg, transparent 0, #000 var(--edge-fade)); }
.tscroll.fade-l.fade-r { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--edge-fade), #000 calc(100% - 72px), transparent); mask-image: linear-gradient(90deg, transparent 0, #000 var(--edge-fade), #000 calc(100% - 72px), transparent); }
.tstop { flex: 0 0 var(--card-w); scroll-snap-align: start; position: relative; padding-top: 52px; display: flex; flex-direction: column; }
.tstop::before { content: ""; position: absolute; top: 10px; left: calc(-1 * var(--card-gap)); right: calc(-1 * var(--card-gap)); height: 1px; background: var(--line-2); }
.tstop:first-child::before { left: 5px; }
.tstop:last-child::before { right: 5px; }
.tstop::after { content: ""; position: absolute; top: 5px; left: 0; width: 11px; height: 11px; border-radius: 50%; background: var(--bg); border: 2px solid var(--event); }
.tstop--upcoming::after { width: 15px; height: 15px; top: 3px; box-shadow: inset 0 0 0 2px var(--bg), inset 0 0 0 3.5px var(--event); }
.tstop-date { position: absolute; top: 22px; left: 0; }
.tcard { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--card-pad) var(--card-pad) 1rem; box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 0.55rem; flex: 1; transition: border-color 0.25s ease; }
.tcard:hover, .tcard:focus-within { border-color: var(--accent); }
/* A talk flagged `"highlight": true` in content/talks.json. Presentation only: the flag never moves a card,
   the strip stays chronological. The gold lives in the 1px border as a gradient (two background layers, one
   clipped to the padding box and one to the border box), so switching it on changes no dimension. The tab
   sits in the 52px of padding above the card, to the right of the date, where the scroller cannot clip it. */
.tstop--highlight .tcard {
  border-color: transparent;
  background-image: linear-gradient(var(--surface), var(--surface)),
    linear-gradient(135deg, var(--gold) 0%, var(--gold-bright) 22%, var(--gold-sheen) 42%, var(--gold-bright) 62%, var(--gold) 100%);
  background-origin: border-box;
  background-clip: padding-box, border-box;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 45%, transparent),
    0 2px 8px -5px color-mix(in srgb, var(--gold) 50%, transparent), var(--shadow);
}
/* The gold stays on hover and focus. Swapping the border to the usual teal would show two rings at once,
   the gold shadow ring outside and a teal border inside it. Keyboard focus stays obvious through the 3px
   accent outline on the focused link, which no highlight rule touches. Hover only deepens the colour:
   the shadow keeps exactly the same geometry, so nothing grows into the scroller's edge and gets cut off. */
.tstop--highlight .tcard:hover, .tstop--highlight .tcard:focus-within {
  border-color: transparent;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 75%, transparent),
    0 2px 8px -5px color-mix(in srgb, var(--gold) 60%, transparent), var(--shadow);
}
/* the status is spelled out as a chip beside the talk's other badges, never carried by the border alone */
.chip--highlight {
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-bright) 55%, var(--gold-sheen) 100%);
  color: var(--gold-ink);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 35%, transparent);
}
/* a stage photo sits in a 16/9 band, the shape the photos are cropped to, on the beats' dot grid */
.tcard-media { margin: calc(-1 * var(--card-pad)) calc(-1 * var(--card-pad)) 0.15rem; aspect-ratio: 16 / 9; display: flex; align-items: center; justify-content: center;
  background: var(--bg-2); background-image: radial-gradient(var(--dot) 1px, transparent 1px); background-size: 18px 18px;
  border-bottom: 1px solid var(--line); border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0; overflow: hidden; }
/* The band takes the 16/9 of the photos, and the photo fills it: cover only ever trims the fraction of a
   pixel a real 16/9 crop is off by, so there is no strip of dot grid above or below the picture. */
.tcard-media img { width: 100%; height: 100%; object-fit: cover; }
.talk-meta { display: flex; flex-wrap: wrap; gap: 0.4rem 0.5rem; align-items: center; }
.tcard h3 { font-size: 1.18rem; }
.tcard .where { color: var(--muted); font-size: 0.88rem; line-height: 1.45; }
.tcard .summary { color: var(--ink-2); font-size: 0.95rem; line-height: 1.55; hyphens: auto; overflow-wrap: break-word; }
.tcard-foot { margin-top: auto; padding-top: 0.6rem; border-top: 1px solid var(--line); display: grid; gap: 0.3rem; }
.tcard-foot .links { display: flex; flex-wrap: wrap; gap: 0.2rem 0.5rem; font-size: 0.88rem; list-style: none; }
.tcard-foot .links li:not(:last-child)::after { content: "·"; color: var(--muted); margin-inline-start: 0.5rem; }
.tcard-foot .related { font-size: 0.88rem; } /* the labels are short now, so they wrap instead of being cut */
.talks-progress { height: 2px; background: var(--line); margin-top: 1rem; border-radius: 1px; overflow: hidden; }
.talks-progress > span { display: block; height: 100%; width: 100%; background: var(--accent); transform-origin: left; transform: scaleX(0); }
@media (prefers-reduced-motion: no-preference) { .talks-progress > span { transition: transform 0.1s linear; } }

/* ---------- projects (service tasks) ---------- */
.cards { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 1.25rem; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.25rem; display: flex; flex-direction: column; gap: 0.6rem; box-shadow: var(--shadow); transition: transform 0.25s var(--ease), border-color 0.25s ease; }
.card:hover, .card:focus-within { border-color: var(--accent); }
.card-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.75rem; align-items: start; }
.card h3 { font-size: 1.35rem; }
.card h3 a { color: var(--ink); text-decoration: none; }
.card h3 a:hover { color: var(--accent-ink); text-decoration: underline; }
.card .meta { color: var(--muted); font-size: 0.85rem; }
.card .summary { color: var(--ink-2); font-size: 1rem; flex: 1; hyphens: auto; overflow-wrap: break-word; }
.card .summary > p { margin: 0 0 0.65rem; }
/* compact case study on a featured card: role, key decision, result */
.facets { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.4rem 1rem; margin: 0; font-size: 0.95rem; }
.facets dt { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); padding-top: 0.25em; }
.facets dd { margin: 0; color: var(--ink-2); }
@media (max-width: 600px) { .facets { grid-template-columns: 1fr; gap: 0.15rem 0; } .facets dd { margin-bottom: 0.6rem; } }
.work-grid--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 1rem; }
@media (max-width: 760px) { .work-grid--wide { grid-template-columns: 1fr; } }
.card .tech-row { display: flex; flex-wrap: wrap; gap: 0.4rem; list-style: none; }
.card .tech-row li { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 0.15rem 0.5rem; }
.card .tech-row .icon { width: 13px; height: 13px; }
.card .links { display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem; font-size: 0.92rem; list-style: none; padding-top: 0.35rem; border-top: 1px solid var(--line); }
.status--active { background: var(--accent-soft); color: var(--accent-ink); }
/* `active` and `maintained` render no chip at all, so they need no rule here */
.status--contribution, .status--handedover { background: transparent; border: 1px solid var(--line-2); color: var(--muted); }
.status--archived { background: transparent; border: 1px dashed var(--line-2); color: var(--muted); }
.status--upstream { background: color-mix(in srgb, var(--event) 18%, transparent); color: color-mix(in srgb, var(--event) 75%, var(--ink)); }

/* ---------- certificates ---------- */
.badge-group + .badge-group { margin-top: 2rem; }
.badges { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 1rem; }
.badge { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1rem; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; transition: border-color 0.15s ease, transform 0.25s var(--ease); }
.badge:hover, .badge:focus-within { border-color: var(--accent); }
.badge img { width: 96px; height: 96px; }
.badge .badge-icon { width: 96px; height: 96px; padding: 20px; color: var(--accent-ink); }
.badge .badge-logo { object-fit: contain; padding: 10px; }
.badge .badge-glyph { width: 96px; height: 96px; padding: 22px; color: var(--accent-ink); fill: currentColor; }
/* an image pair for both themes: the light one by default, the dark one in dark mode */
.only-dark { display: none; }
:root[data-theme="dark"] .only-dark { display: block; }
:root[data-theme="dark"] .only-light { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .only-dark { display: block; }
  :root:not([data-theme="light"]) .only-light { display: none; }
}
.badge .name { font-weight: 600; font-size: 0.92rem; line-height: 1.3; }
.badge .name a { color: var(--ink); text-decoration: none; }
.badge .name a::after { content: ""; position: absolute; inset: 0; }
.badge .dates { font-family: var(--font-mono); font-size: 0.76rem; color: var(--muted); }
.badge .issuer { font-size: 0.8rem; line-height: 1.3; color: var(--ink-2); }
.cert-foot { margin-top: 1.5rem; }

/* ---------- footer (end event) ---------- */
.site-footer { border-top: 1px solid var(--line); background: var(--bg-2); padding-block: clamp(2.5rem, 5vw, 4rem) 1.5rem; font-size: 0.95rem; }
.footer-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; }
@media (max-width: 760px) { .footer-grid { grid-template-columns: 1fr; } }
.site-footer h3 { font-family: var(--font-sans); font-size: 0.95rem; font-weight: 700; margin-bottom: 0.5rem; letter-spacing: 0; }
.sources { list-style: none; display: flex; flex-wrap: wrap; gap: 0.3rem 0.5rem; margin-top: 0.75rem; font-size: 0.9rem; }
.sources li:not(:last-child)::after { content: "·"; color: var(--muted); margin-inline-start: 0.5rem; }
.footer-bar { display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; align-items: center; margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid var(--line); color: var(--muted); font-size: 0.85rem; }
.footer-bar ul { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; list-style: none; }
.footer-bar .spacer { flex: 1; }

/* Floating in the corner rather than a footer-bar link, so it stays reachable while reading, not only at the
   end of the page. Shown by default: main.js only ever adds is-hidden, once scrolled past the first screen,
   so a reader without JavaScript still has a permanent, working way back to the top. */
.to-top {
  position: fixed; right: clamp(1rem, 4vw, 2rem); bottom: clamp(1rem, 4vw, 2rem); z-index: 40;
  display: flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border-radius: 6px; background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow);
  font-size: 1.25rem; line-height: 1; text-decoration: none;
  transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.15s ease;
}
.to-top:hover { background: var(--accent-hover); }
.to-top.is-hidden { opacity: 0; transform: translateY(14px); pointer-events: none; }

/* ---------- legal + 404 ---------- */
.page { padding-block: clamp(2.5rem, 6vw, 4.5rem); }
.page .wrap { padding-inline-start: var(--gutter); }
.legal { max-width: 72ch; }
.legal h1 { font-size: clamp(2.2rem, 4vw, 3rem); margin-bottom: 1rem; }
.legal h2 { font-family: var(--font-sans); font-size: 1.05rem; font-weight: 700; margin-top: 1.75rem; margin-bottom: 0.4rem; letter-spacing: 0; }
.legal p { color: var(--ink-2); }
.legal .legal-lead { font-size: 1.1rem; color: var(--ink); }
.legal .legal-meta { color: var(--muted); font-size: 0.9rem; margin-top: 1.5rem; }
.legal .legal-en { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--line); font-family: var(--font-display); font-size: 1.5rem; }
.notfound { text-align: center; padding-block: clamp(4rem, 12vw, 9rem); }
.notfound .mark { width: 64px; height: 64px; margin: 0 auto 1.5rem; }
.notfound p { color: var(--ink-2); }
.notfound .alt { margin-top: 2rem; color: var(--muted); font-size: 0.92rem; }

/* ---------- print ---------- */
@media print {
  .site-header, .controls, .skip, .theme-toggle, .rail, .flow-end { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  a { color: inherit; text-decoration: none; }
  .card, .badge, .career li, .series-tile, .work-tile, .compact-list > li { break-inside: avoid; box-shadow: none; }
}

/* Reading, progressive disclosure and a clear route back into conversation. */
.archive { margin-top: 1.75rem; border-block: 1px solid var(--line-2); }
.archive > summary { min-height: 56px; padding: 1rem .25rem; cursor: pointer; color: var(--accent-ink); font-weight: 600; }
.archive > summary:hover { color: var(--accent-hover); }
.archive-count { margin-inline-start: .5rem; font-family: var(--font-mono); color: var(--muted); font-size: .875rem; }
.archive[open] > summary { margin-bottom: 1rem; }
.archive > .compact-list { margin-bottom: 1rem; }
.contact-section { position: relative; padding-block: clamp(2.5rem,5vw,4rem); background: var(--accent-soft); border-top: 1px solid var(--line-2); }
.contact-layout { display: flex; align-items: center; gap: 2rem; justify-content: space-between; }
.contact-layout > div { max-width: 38rem; }
.contact-layout h2 { font-size: clamp(1.8rem,3vw,2.5rem); }
.contact-layout p { margin-top: .75rem; color: var(--ink-2); }
.contact-layout .btn { flex-shrink: 0; }
.cards > *, .work-grid > *, .hero-grid > *, .footer-grid > * { min-width: 0; }
.card, .work-tile, .series-tile, .badge, .contact-layout { overflow-wrap: anywhere; }
.btn { min-height: 44px; }
@media (max-width: 860px) {
  .hero-grid { grid-template-columns: minmax(0,1fr) 140px; gap: 1.5rem; align-items: start; }
  .portrait { width: 120px; height: 120px; padding: 6px; margin: 12px 0 0; }
  .portrait::before { inset: -8px; border-width: 1px; }
}
@media (max-width: 600px) {
  .hero-grid { grid-template-columns: 1fr; gap: 1.75rem; }
  .hero h1 { font-size: clamp(2.7rem,12vw,4rem); }
  .hero .lead { font-size: 1.2rem; }
  .hero .kicker { font-size: .8rem; line-height: 1.7; }
  .hero-grid { position: relative; }
  .hero-copy > .kicker { padding-inline-end: 90px; min-height: 80px; }
  .portrait-wrap { position: absolute; top: 0; right: 8px; display: grid; }
  .portrait { width: 64px; height: 64px; padding: 3px; border-width: 1px; margin-top: 8px; }
  .portrait::before { inset: -6px; }
  .hero-actions { gap: .6rem; }
  .hero-actions .btn { padding-inline: .8rem; }
  .find-me { margin-top: 1.5rem; }
  .contact-layout { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
  .chapter .beat-sub { font-size: 1.0625rem; }
  .card .tech-row li, .chip, .kicker { white-space: normal; }
}
@media print {
  .beat { position: static; }
  .beat-inner { opacity: 1; transform: none; }
  .hero-actions, .find-me, .contact-section, .to-top { display: none; }
  details::details-content { content-visibility: visible; }
}

@media (min-width: 960px) {
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card--featured { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.35fr); grid-template-areas: "heading summary" "meta summary" "tech summary" ". links"; grid-template-rows: auto auto 1fr auto; align-items: start; gap: .8rem 2rem; padding: 1.5rem 2rem; border-top: 3px solid var(--accent); }
  .card--featured .card-head { grid-area: heading; flex-direction: column; align-items: flex-start; gap: .75rem; }
  .card--featured h3 { font-size: 1.8rem; }
  .card--featured .meta { grid-area: meta; }
  .card--featured .summary { grid-area: summary; margin: 0; }
  .card--featured .tech-row { grid-area: tech; align-content: start; }
  .card--featured .links { grid-area: links; }
}

/* ---------- brand colours on hover (from Simple Icons metadata) ---------- */
.tech li[data-slug="amazonwebservices"] { --brand: #232F3E; }
.tech li[data-slug="anthropic"] { --brand: #191919; }
.tech li[data-slug="apachekafka"] { --brand: #231F20; }
.tech li[data-slug="apachemaven"] { --brand: #C71A36; }
.tech li[data-slug="argo"] { --brand: #EF7B4D; }
.tech li[data-slug="azure"] { --brand: #0078D4; }
.tech li[data-slug="bluesky"] { --brand: #0285FF; }
.tech li[data-slug="camunda"] { --brand: #FC5D0D; }
.tech li[data-slug="claude"] { --brand: #D97757; }
.tech li[data-slug="cloudflare"] { --brand: #F38020; }
.tech li[data-slug="credly"] { --brand: #FF6B00; }
.tech li[data-slug="docker"] { --brand: #2496ED; }
.tech li[data-slug="excalidraw"] { --brand: #6965DB; }
.tech li[data-slug="flux"] { --brand: #5468FF; }
.tech li[data-slug="github"] { --brand: #181717; }
.tech li[data-slug="gradle"] { --brand: #02303A; }
.tech li[data-slug="grafana"] { --brand: #F46800; }
.tech li[data-slug="hashicorp"] { --brand: #000000; }
.tech li[data-slug="helm"] { --brand: #0F1689; }
.tech li[data-slug="json"] { --brand: #000000; }
.tech li[data-slug="keycloak"] { --brand: #4D4D4D; }
.tech li[data-slug="kotlin"] { --brand: #7F52FF; }
.tech li[data-slug="kubernetes"] { --brand: #326CE5; }
.tech li[data-slug="linkedin"] { --brand: #0A66C2; }
.tech li[data-slug="medium"] { --brand: #000000; }
.tech li[data-slug="openai"] { --brand: #412991; }
.tech li[data-slug="openapiinitiative"] { --brand: #6BA539; }
.tech li[data-slug="openjdk"] { --brand: #000000; }
.tech li[data-slug="opensearch"] { --brand: #005EB8; }
.tech li[data-slug="opentofu"] { --brand: #FFDA18; }
.tech li[data-slug="postgresql"] { --brand: #4169E1; }
.tech li[data-slug="prometheus"] { --brand: #E6522C; }
.tech li[data-slug="spring"] { --brand: #6DB33F; }
.tech li[data-slug="springboot"] { --brand: #6DB33F; }
.tech li[data-slug="stackit"] { --brand: #06555F; }
.tech li[data-slug="substack"] { --brand: #FF6719; }
.tech li[data-slug="terraform"] { --brand: #844FBA; }
.tech li[data-slug="vault"] { --brand: #FFEC6E; }
.tech li[data-slug="youtube"] { --brand: #FF0000; }
