@font-face { font-family: 'Montserrat'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/montserrat-latin-400-normal.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: 'Montserrat'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/montserrat-latin-500-normal.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: 'Montserrat'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/montserrat-latin-600-normal.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: 'Montserrat'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/montserrat-latin-ext-400-normal.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: 'Montserrat'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/montserrat-latin-ext-500-normal.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: 'Montserrat'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/montserrat-latin-ext-600-normal.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: 'Montserrat'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/montserrat-cyrillic-400-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'Montserrat'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/montserrat-cyrillic-500-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'Montserrat'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/montserrat-cyrillic-600-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-mono-latin-400-normal.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: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-mono-latin-500-normal.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: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-mono-latin-ext-400-normal.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: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-mono-latin-ext-500-normal.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: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-mono-cyrillic-400-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-mono-cyrillic-500-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'Commissioner'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/commissioner-greek-400-normal.woff2') format('woff2'); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: 'Commissioner'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/commissioner-greek-500-normal.woff2') format('woff2'); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: 'Commissioner'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/commissioner-greek-600-normal.woff2') format('woff2'); unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-400-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-500-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-600-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-ext-400-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-ext-500-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ibm-plex-sans-latin-ext-600-normal.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: 'IBM Plex Sans'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/ibm-plex-sans-cyrillic-400-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/ibm-plex-sans-cyrillic-500-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/ibm-plex-sans-cyrillic-600-normal.woff2') format('woff2'); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
/* Arial scaled to the web fonts' width and height, so text does not jump when they arrive */
@font-face { font-family: 'Montserrat Fallback'; src: local('Arial'), local('ArialMT'), local('Liberation Sans'); size-adjust: 113.65%; ascent-override: 85.17%; descent-override: 22.09%; line-gap-override: 0%; }
@font-face { font-family: 'IBM Plex Sans Fallback'; src: local('Arial'), local('ArialMT'), local('Liberation Sans'); size-adjust: 100.95%; ascent-override: 101.54%; descent-override: 27.24%; line-gap-override: 0%; }

/* Layout: one calm column of statements, each opened by a headline + dark bar (the LinkedIn banner motif); the hero pairs it with a code review that shows "AI-assisted, human-led" at work. */
:root {
  /* one dark page in both schemes: the sections differ by tone, not by light/dark bands.
     Every colour of the page is named here once; the rest of the CSS and the canvas drawings only use the names */
  --page-rgb: 15, 14, 16;
  --page: rgb(var(--page-rgb));
  --bg: var(--page);
  --fg: #F2F0F1;
  --text: #DEDCDD; /* running text, about 87 % white: long paragraphs do not glare on the dark ground (14 : 1) */
  --muted: #BAB5B8;
  --line: #2A272A;
  --surface: #18171A;
  --bar: var(--fg);
  --bar-fg: #121113;
  /* the two voices: cyan is the human, amber the AI; as r, g, b too, so any shade can take an alpha */
  --human-rgb: 63, 224, 245;
  --human: rgb(var(--human-rgb));
  --ai-rgb: 255, 180, 84;
  --ai: rgb(var(--ai-rgb));
  --ai-light: #FFE2B8;
  --ai-dark: #C77B1E;
  --accent: var(--human);
  --grid-ink: rgba(242, 240, 241, 0.12);
  --grid-glow: rgba(var(--human-rgb), 0.3);
  /* the neon stage of the hero and the game: bluer blacks and whites; its neon is the human cyan, --neon-light a paler tint */
  --neon-light: #7FF0FF;
  --stage-bg: #05070B;
  --space: #020306; /* deep space behind the stars, the Earth and the Moon */
  --stage-glow: #0A2131;
  --stage-surface: #0A1219;
  --stage-line: #1B2A34;
  --stage-dim: #8FA6B0;
  --stage-muted: #A9BDC6;
  --stage-fg: #EAF6FA;
  --struck: rgba(240, 248, 255, 0.5); /* the word that is not quite right, faded back */
  /* plain black and white: the frame, light on dark, shadows, the snow */
  --black-rgb: 0, 0, 0;
  --frame-bg: rgb(var(--black-rgb));
  --white-rgb: 255, 255, 255;
  --white: rgb(var(--white-rgb));
  --slate-rgb: 110, 120, 140;
  /* buttons, status lights and the terminal window */
  --ghost: #232125;
  --ghost-hover: #2E2B30;
  --ok: #5EE6A8;
  --status-wait: #F2B24C;
  --status-online: #3DD68C;
  --status-offline: #9A9599;
  --win-close: #FF5F57;
  --win-min: #FEBC2E;
  --win-max: #28C840;
  color-scheme: dark;
  /* type scale: five sizes */
  --fs-s: 0.875rem;
  --fs-m: clamp(1rem, 0.93rem + 0.3vw, 1.1875rem);
  --fs-l: clamp(1.2rem, 1rem + 0.6vw, 1.5rem);
  --fs-xl: clamp(2rem, 1.3rem + 2.6vw, 3.75rem);
  --fs-xxl: clamp(2.4rem, 1rem + 5vw, 5.5rem);
  --font-display: 'Montserrat', 'Commissioner', 'Montserrat Fallback', 'Helvetica Neue', Arial, sans-serif;
  --font-body: 'IBM Plex Sans', 'Commissioner', 'IBM Plex Sans Fallback', 'Helvetica Neue', Arial, sans-serif;
  /* three line heights and three tracking steps carry the whole page */
  --lh-tight: 1.05;
  --lh-snug: 1.3;
  --lh-body: 1.6;
  --ls-display: -0.03em;
  --ls-caps: 0.08em;
  --ls-caps-wide: 0.14em;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  --wrap: 1280px;
  /* "About" is a terminal band: one dark look in both themes, on purpose */
  --term-bg-rgb: 11, 11, 12;
  --term-bg: rgb(var(--term-bg-rgb));
  --term-surface: #141315;
  --term-fg: #EDEBEC;
  --term-muted: #ADA8AB;
  --term-line: #262326;
  --term-accent: var(--human);
}
html[lang="en"] { --fs-xxl: clamp(2.3rem, 1rem + 4.2vw, 4.75rem); }
html[lang="ru"], html[lang="el"] { --fs-xxl: clamp(1.9rem, 0.9rem + 3.4vw, 4rem); --fs-xl: clamp(1.8rem, 1.1rem + 2.2vw, 3.25rem); }
html[lang="sr"] { --fs-xxl: clamp(2.2rem, 1rem + 4.4vw, 5rem); }
@media (max-width: 480px) { html[lang="ru"] { --fs-xl: 1.65rem; } }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-m);
  line-height: var(--lh-body);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}
/* long German compounds break cleanly in running text; statements and the terminal never hyphenate */
main p, main li { -webkit-hyphens: auto; hyphens: auto; hyphenate-limit-chars: 7 3 3; }
main .lede, .cli p, .cli li { -webkit-hyphens: manual; hyphens: manual; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-left: max(24px, env(safe-area-inset-left, 0px));
  padding-right: max(24px, env(safe-area-inset-right, 0px));
}
@media (max-width: 480px) {
  .wrap {
    padding-left: max(16px, env(safe-area-inset-left, 0px));
    padding-right: max(16px, env(safe-area-inset-right, 0px));
  }
}

/* The brand device: text on a light bar, one bar per line, its ends skewed like a parallelogram
   (after pepelsbey.dev/articles/skewed-highlight). One gradient at 103deg draws the whole shape, so there is no seam where
   slant and edge meet: its isolines lean like "/", 0.35em cuts the slant from the bottom-left corner of a line (the bar
   is about 1.53em tall, 1.53em * sin 13deg = 0.345em) and the same from the top-right. box-decoration-break: clone gives
   every wrapped line its own bar with both ends; the 1 px ramps keep the slants smooth. --slope 77deg mirrors it ("\"). */
.bar {
  --mark: var(--bar);
  background: linear-gradient(var(--slope, 103deg),
    transparent calc(0.35em - 0.5px), var(--mark) calc(0.35em + 0.5px),
    var(--mark) calc(100% - 0.35em - 0.5px), transparent calc(100% - 0.35em + 0.5px));
  color: var(--bar-fg);
  padding: 0.12em 0.55em 0.18em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  line-height: 1.85; /* room for the bar padding between wrapped lines */
}


/* Header */
.site-head {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 10;
  height: var(--tab-d);
  margin-bottom: calc(-1 * var(--tab-d));
}
.site-head .wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 100%;
}

/* Hero */
/* The hero is a window into space in both themes, on purpose: stars and the Earth only work on black */
.hero {
  position: relative;
  overflow: hidden;
  --bg: var(--stage-bg);
  --fg: var(--stage-fg);
  --muted: var(--stage-muted);
  --line: var(--stage-line);
  --surface: var(--stage-surface);
  --bar: var(--stage-fg);
  --bar-fg: var(--stage-bg);
  --accent: var(--human);
  --plate: #121C25; /* the dark plates of the quiz */
  color-scheme: dark;
  color: var(--fg);
  background: var(--space);
}
.hero .review-card { background: var(--stage-surface); border-color: rgba(var(--human-rgb), 0.22); }
.retro-grid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  z-index: 0;
}
.hero .wrap { position: relative; z-index: 1; }
/* the Earth turns for as long as the page is open, so it gets a way to stop (WCAG 2.2.2); quiet, in the empty corner */
.earth-pause {
  position: absolute;
  z-index: 2;
  right: calc(max((100% - var(--wrap)) / 2, 0px) + 11px);
  bottom: calc(var(--frame) + 30px);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: rgba(var(--white-rgb), 0.45);
  cursor: pointer;
  transition: color 0.15s ease, opacity 0.45s ease;
}
.earth-pause:hover, .earth-pause:focus-visible { color: var(--fg); }
.earth-pause svg { width: 14px; height: 14px; fill: currentColor; }
.earth-pause .i-play, .earth-pause.is-paused .i-pause { display: none; }
.earth-pause.is-paused .i-play { display: block; }
.hero.quiz-shown .earth-pause { visibility: hidden; opacity: 0; }
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(var(--page-rgb), 0) calc(100% - clamp(64px, 10vw, 140px)), var(--page));
  pointer-events: none;
  z-index: 0;
}

/* CRT feel on the dark terminal bands */
.about-band, .next-band { position: relative; }
.about-band .wrap, .next-band .wrap { position: relative; z-index: 1; }

.hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: center;
  /* the bottom padding keeps the quiz clear of the "scroll down" tab */
  padding-block: calc(var(--tab-d) + clamp(40px, 6vw, 88px)) calc(var(--tab-d) + clamp(32px, 4vw, 64px));
}
.hero-text { display: flex; flex-direction: column; gap: 28px; min-width: 0; }
.hero-side { display: flex; flex-direction: column; gap: 28px; min-width: 0; }
.hero h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-xxl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}
/* headline and the line under it are one sentence: screen readers get it whole from the h1 (hero.sentence, .sr-only),
   the two visible halves are hidden from them */
/* the word that is not quite right: read first, then it fades back */
.hero h1 .squiggle { animation: struck-fade 0.8s ease 1.2s both; }
@keyframes struck-fade { from { color: inherit; } to { color: var(--struck); } }
@media (prefers-reduced-motion: reduce) { .hero h1 .squiggle { animation: none; color: var(--struck); } }
.hero .lede {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-l);
  max-width: 32ch;
  text-wrap: balance;
}
.role {
  margin: 0;
  color: var(--fg);
  font-weight: 500;
  font-size: var(--fs-m);
  line-height: var(--lh-body);
}
.role strong { color: var(--fg); font-weight: 600; }
.role .sep { display: inline-block; width: 4px; height: 4px; margin: 0 10px; vertical-align: middle; border-radius: 50%; background: var(--muted); }
/* the role on a black bar with white letters, slanting the other way than the white bar above it; on the phone
   it wraps into two even lines instead of leaving one word alone */
.role { text-wrap: balance; }
.role .bar { --slope: 77deg; --mark: rgb(var(--black-rgb)); color: var(--bar); }
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 22px;
  border-radius: 4px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-m);
  text-decoration: none;
  border: 0;
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
.btn-primary { background: var(--bar); color: var(--bar-fg); }
.btn-primary:hover { background: var(--white); }
.btn-ghost { background: var(--ghost); color: var(--fg); }
.btn-ghost:hover { background: var(--ghost-hover); }
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.98); }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn:hover { transform: none; } }
.btn svg { width: 18px; height: 18px; flex: none; }

/* Code review card: the subject's own artefact */
.review {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}
.review-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  font-size: var(--fs-s);
  line-height: var(--lh-body);
}
.review-card .code { font-size: var(--fs-s); }
.review-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
}
.review-head .file { color: var(--fg); font-weight: 500; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-s);
  font-weight: 500;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg);
  white-space: nowrap;
}
.chip-ok { background: var(--bar); color: var(--bar-fg); border-color: var(--bar); }
.chip svg { width: 12px; height: 12px; }
.chat-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.chat-link:hover { text-decoration-thickness: 2px; }
.hunk { padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.hunk + .hunk { border-top: 1px dashed var(--line); }
.hunk-label { color: var(--muted); font-size: var(--fs-s); }
.code {
  margin: 0;
  overflow-x: auto;
  white-space: pre;
  color: var(--fg);
  font-family: var(--font-mono);
}
.code mark { background: transparent; color: var(--accent); font-weight: 500; }
.comment {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 2px 0;
  padding: 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: var(--fs-m);
  line-height: var(--lh-body);
}
.avatar {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bar);
  color: var(--bar-fg);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-s);
}
.comment p { margin: 0; min-width: 0; }
.comment b { font-weight: 600; }
.review-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--line);
  color: var(--muted);
}
.review figcaption {
  font-size: var(--fs-s);
  color: var(--muted);
}

/* Review carousel */
.carousel { overflow: hidden; transition: height 0.3s ease; }
.track {
  display: flex;
  align-items: flex-start;
  transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
  touch-action: pan-y;
}
/* every slide has the same height; what appears after an answer scrolls inside */
.slide { flex: 0 0 100%; min-width: 0; display: flex; flex-direction: column; position: relative; height: var(--slide-h, auto); overflow-y: auto; }
.slide .review-foot { margin-top: auto; justify-content: flex-end; }
.slide .review-head { justify-content: flex-end; }
@media (max-width: 420px) {
  .dot { width: 18px; }
}
[hidden] { display: none !important; }

/* Quiz: the visitor decides first, the "AI" applauds, then the verdict */
.quiz { display: none; flex-direction: column; gap: 10px; }
.quiz-on .quiz { display: flex; }
.quiz-on .slide:not(.answered) .comment,
.quiz-on .slide:not(.answered) .hunk-fix,
.quiz-on .slide:not(.answered) .review-foot { display: none; }
.quiz-q {
  margin: 4px 0 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-m);
  color: var(--fg);
}
.quiz-opts { display: flex; flex-direction: column; gap: 6px; }
.opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 8px 12px;
  text-align: left;
  font-family: var(--font-body);
  font-size: var(--fs-m);
  line-height: var(--lh-snug);
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
  transition: border-color 0.15s ease, opacity 0.15s ease, transform 0.12s ease;
}
.opt:hover:not(:disabled) { border-color: var(--fg); }
.opt:active:not(:disabled) { transform: scale(0.985); }
.opt:disabled { cursor: default; }
.opt-key {
  flex: none;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: 4px;
  background: var(--surface);
  font-size: var(--fs-s);
  font-weight: 600;
  color: var(--muted);
}
.answered .opt { opacity: 0.45; }
.answered .opt.is-correct, .answered .opt.is-picked { opacity: 1; }
.opt.is-correct { border-color: var(--fg); }
.opt.is-correct .opt-key { background: var(--bar); color: var(--bar-fg); }
.opt.is-picked:not(.is-correct) { border-color: var(--accent); }
.opt.is-picked:not(.is-correct) .opt-key { background: var(--accent); color: var(--bg); }
.ai-reply {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px;
  border: 1px dashed var(--line);
  border-radius: 6px;
  font-family: var(--font-body);
  font-size: var(--fs-m);
  line-height: var(--lh-body);
}
.ai-reply p { margin: 0; min-width: 0; }
.ai-reply b { font-weight: 600; }
.avatar-ai {
  background: transparent;
  color: var(--muted);
  border: 1px dashed var(--muted);
  border-radius: 4px;
  font-weight: 600;
}
.ai-text.thinking { color: var(--muted); letter-spacing: var(--ls-caps-wide); }
.verdict { font-weight: 600; margin-right: 0.35em; }
.verdict.is-wrong { color: var(--accent); }
/* the result covers the card once all ten are answered */
.review-card.carousel { position: relative; }
.quiz-score {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow-y: auto;
  background: var(--surface);
  animation: score-in 0.35s ease both;
}
.quiz-score::-webkit-scrollbar { width: 6px; }
.quiz-score::-webkit-scrollbar-thumb { background: rgba(var(--human-rgb), 0.35); border-radius: 3px; }
@keyframes score-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.quiz-score .comment { margin: 2px 0; }
/* the two ways on sit side by side, like a final pair of answers; the bonus is the highlighted one */
.quiz-score .quiz-opts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 2px; }
.quiz-score .quiz-bonus { border-color: var(--fg); }
.quiz-score .quiz-bonus .opt-key { background: var(--bar); color: var(--bar-fg); }
@media (prefers-reduced-motion: reduce) { .quiz-score { animation: none; } }

/* Quiz stage: like a quiz show, every part keeps its place. The ladder on top, the case as a script (the AI's
   suggestion turns into Alex's revision in place), the question with its answers, and the two voices below them:
   the AI's praise, Alex's verdict and the way on. Everything that can appear is laid out from the start and only
   shown, so the slide never changes height. Wrong is amber, right is cyan, and each also gets a word. */
.review-card.stage { --amber: var(--ai); display: flex; flex-direction: column; gap: 10px; padding: 12px 18px 16px; }
.stage-body { position: relative; }
/* every question fills the card; the footer with the way on sits at the bottom, in the same place each time */
.stage .track { display: grid; align-items: stretch; }
.stage .slide { grid-area: 1 / 1; height: auto; overflow: visible; gap: 12px; visibility: hidden; opacity: 0; transition: opacity 0.3s ease, visibility 0s linear 0.3s; }
.stage .slide.is-current { visibility: visible; opacity: 1; transition: opacity 0.3s ease, visibility 0s; }
.stage .case { display: grid; }
.stage .case > .hunk { grid-area: 1 / 1; min-width: 0; transition: opacity 0.3s ease, visibility 0s; }
/* long lines wrap instead of running past the edge */
.stage .case .code { white-space: pre-wrap; overflow-wrap: anywhere; overflow: visible; }
.stage.quiz-on .slide .hunk-fix { display: grid; border: 0; visibility: hidden; opacity: 0; }
.stage.quiz-on .slide.answered .hunk-ai { visibility: hidden; opacity: 0; }
.stage.quiz-on .slide.answered .hunk-fix { visibility: visible; opacity: 1; }
.stage .quiz-q { margin: 0; }
.opt-tag { display: none; }
.stage .opt-tag { display: grid; justify-items: end; flex: none; margin-left: auto; padding-left: 10px; font-family: var(--font-body); font-size: var(--fs-s); font-weight: 600; white-space: nowrap; visibility: hidden; }
.stage .opt-tag > span { grid-area: 1 / 1; }
.stage .answered .opt.is-correct [data-i18n="quiz.right"], .stage .answered .opt.is-picked:not(.is-correct) [data-i18n="quiz.pick"] { visibility: visible; }
.stage-foot { display: grid; margin-top: auto; }
.stage-foot > * { grid-area: 1 / 1; }
.stage-result { display: flex; flex-direction: column; gap: 6px; visibility: hidden; }
.stage .answering .stage-result, .stage .answered .stage-result { visibility: visible; }
.stage .ai-reply { padding: 0; border: 0; font-size: inherit; line-height: inherit; }
.ai-say { display: grid; }
.ai-say > .ai-sizer, .ai-say > .ai-text { grid-area: 1 / 1; }
.ai-sizer { display: grid; visibility: hidden; }
.ai-sizer > span { grid-area: 1 / 1; }
.stage-row { display: flex; align-items: flex-end; gap: 14px; visibility: hidden; }
.stage .answered .stage-row { visibility: visible; }
.stage.quiz-on .slide .comment { display: block; flex: 1; min-width: 0; margin: 0; padding: 0; border: 0; background: none; font-size: inherit; line-height: inherit; }
.verdict-box { display: inline-grid; margin-right: 0.35em; font-weight: 600; }
.verdict-box > *, .verdict-size > span { grid-area: 1 / 1; }
.verdict-size { display: grid; visibility: hidden; }
.verdict-box .verdict { margin-right: 0; }
.stage-next { display: inline-grid; justify-items: center; align-items: center; flex: none; white-space: nowrap; cursor: pointer; }
.stage-next > span { grid-area: 1 / 1; }
/* "Next" until every question has an answer, then "Result" */
.stage-next > span + span, .quiz-done .stage-next > span:first-child { visibility: hidden; }
.quiz-done .stage-next > span + span { visibility: inherit; }
/* narrow cards (small laptops): slightly tighter spacing, so the quiz still fits one screen */
.review-card.stage { container-type: inline-size; }
@container (max-width: 420px) {
  .stage .slide { gap: 10px; }
  .stage .quiz { gap: 8px; }
  .stage-foot { padding-top: 8px; }
}
/* the quiz has no frame or background of its own and sits straight on the page */
.hero .review-card.stage { background: transparent; border-color: transparent; }
/* without a background of its own the result no longer covers the question beneath it */
.stage-body:has(> .quiz-score:not([hidden])) > .track { opacity: 0; }
@media (max-width: 860px) {
  /* phones and narrow windows: the hero text fills the first screen, the first question follows below */
  .hero .wrap { row-gap: 0; }
  .hero-text { min-height: calc(100svh - 2 * var(--frame) - var(--tab-d) - clamp(40px, 6vw, 88px)); justify-content: center; }
  .hero .quiz-teaser { margin-top: calc(var(--tab-d) + 16px); }
}
@media (prefers-reduced-motion: reduce) {
  .stage .slide, .stage .slide.is-current, .stage .case > .hunk, .stage-next, .stage-back { transition: none; }
}
/* Hero: only the first question, as a way in. An answer opens the quiz on a slide of its own.
   No card: the case reads like a script, who speaks on the left and each voice on a bar in its colour (the client
   white, the AI orange). Below it the question and three small plates in the slant of the bars, like a TV quiz,
   only as wide as the longest answer, so the headline on the left keeps the stage. */
.quiz-teaser { --plate-h: 44px; gap: 0; container-type: inline-size; }
.quiz-teaser .case { display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: 14px; row-gap: 20px; align-items: baseline; }
.case-who { font-weight: 600; color: var(--muted); }
.case-who.is-ai { color: var(--ai); }
.case-say { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: var(--fs-l); line-height: 1.85; }
.case-say.is-ai { font-size: var(--fs-m); line-height: 1.9; }
.case-say.is-ai .bar { --mark: var(--ai); }
.quiz-teaser .quiz-q { margin: 26px 0 14px; font-family: var(--font-display); font-weight: 500; font-size: clamp(1.5rem, 1rem + 1vw, 2rem); line-height: var(--lh-tight); letter-spacing: -0.02em; }
.quiz-teaser .quiz-opts { display: grid; grid-template-columns: fit-content(100%); gap: 8px; }
/* a plate: the button keeps its rectangle for the pointer, a clipped layer behind the text draws the slant
   (tan 13deg = 0.2309, the angle of the bars) */
.quiz-teaser .opt, .teaser-go { --slant: calc(var(--plate-h) * 0.2309); position: relative; isolation: isolate; border: 0; border-radius: 0; background: none; }
.quiz-teaser .opt { min-height: var(--plate-h); padding: 0 calc(var(--slant) + 16px) 0 calc(var(--slant) + 12px); gap: 12px; font-family: var(--font-display); font-weight: 500; font-size: var(--fs-m); transition: color 0.15s ease, opacity 0.15s ease, transform 0.12s ease; }
.quiz-teaser .opt::before, .teaser-go::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--plate); clip-path: polygon(var(--slant) 0, 100% 0, calc(100% - var(--slant)) 100%, 0 100%); transition: background-color 0.15s ease; }
/* keyboard focus: a 2px ring in the same slant, 3px off the plate, instead of the rectangular outline.
   5px out on top and bottom is 6.29px out across the slant (5px * (1 / cos 13deg + tan 13deg)). */
.quiz-teaser .opt:focus-visible, .teaser-go:focus-visible { outline: none; }
.quiz-teaser .opt::after, .teaser-go::after { content: ""; position: absolute; inset: -5px -6.29px; z-index: -1; background: var(--accent); pointer-events: none; visibility: hidden;
  clip-path: polygon(evenodd, calc(var(--slant) + 2.31px) 0, 100% 0, calc(100% - var(--slant) - 2.31px) 100%, 0 100%, calc(var(--slant) + 2.31px) 0,
    calc(var(--slant) + 3.9px) 2px, calc(100% - 2.51px) 2px, calc(100% - var(--slant) - 3.9px) calc(100% - 2px), 2.51px calc(100% - 2px), calc(var(--slant) + 3.9px) 2px); }
.quiz-teaser .opt:focus-visible::after, .teaser-go:focus-visible::after { visibility: visible; }
.quiz-teaser .opt-key { width: auto; height: auto; min-width: 1em; background: none; border-radius: 0; font-size: var(--fs-s); color: var(--human); transition: color 0.15s ease; }
.quiz-teaser .opt:hover:not(:disabled)::before, .quiz-teaser .opt:focus-visible::before { background: var(--bar); }
.quiz-teaser .opt:hover:not(:disabled), .quiz-teaser .opt:focus-visible { color: var(--bar-fg); }
/* after the first answer the plates show it, like the quiz does: your pick orange, the right one cyan */
.quiz-teaser .opt.is-correct::before { background: var(--human); }
.quiz-teaser .opt.is-picked:not(.is-correct)::before { background: var(--ai); }
.quiz-teaser .opt.is-correct, .quiz-teaser .opt.is-picked { color: var(--bar-fg); }
.quiz-teaser .opt:hover:not(:disabled) .opt-key, .quiz-teaser .opt:focus-visible .opt-key,
.quiz-teaser .opt.is-correct .opt-key, .quiz-teaser .opt.is-picked .opt-key { background: none; color: inherit; }
.quiz-teaser.is-joined .opt-tag { display: grid; justify-items: end; flex: none; margin-left: auto; padding-left: 8px; font-family: var(--font-body); font-weight: 600; font-size: var(--fs-s); white-space: nowrap; }
.quiz-teaser .opt-tag > span { grid-area: 1 / 1; visibility: hidden; }
.quiz-teaser .opt.is-correct [data-i18n="quiz.right"], .quiz-teaser .opt.is-picked:not(.is-correct) [data-i18n="quiz.pick"] { visibility: visible; }
.quiz-teaser.is-joined .opt:not(.is-correct):not(.is-picked) { opacity: 0.45; }
/* and offers the way back in, on a white plate */
.teaser-resume { display: flex; margin-top: 18px; }
.teaser-resume[hidden] { display: none; }
.teaser-go { --plate: var(--bar); --plate-h: 44px; display: inline-grid; justify-items: center; min-height: var(--plate-h); padding: 0 calc(var(--slant) + 14px); color: var(--bar-fg); font-family: var(--font-display); font-weight: 500; font-size: var(--fs-m); white-space: nowrap; cursor: pointer; transition: transform 0.12s ease; }
.teaser-go > span { grid-area: 1 / 1; align-self: center; }
.teaser-go > span + span, .teaser-go.is-done > span:first-child { visibility: hidden; }
.teaser-go.is-done > span + span { visibility: visible; }
.teaser-go:hover { --plate: var(--white); }
.teaser-go:active { transform: scale(0.985); }
@container (width < 430px) {
  /* narrow card (phone, small laptop): who speaks stands above the line, like in a play, so the AI's lines keep their breaks */
  .quiz-teaser .case { grid-template-columns: minmax(0, 1fr); row-gap: 2px; }
  .quiz-teaser .case-who:not(:first-child) { margin-top: 14px; }
  /* after the answer the word goes under the answer instead of beside it, otherwise the longer languages break the
     answer onto two lines; the plate grows to two lines in the same slant */
  .quiz-teaser.is-joined .opt:is(.is-picked, .is-correct) { --plate-h: 64px; display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: center; align-items: baseline; row-gap: 0; }
  .quiz-teaser.is-joined .opt:is(.is-picked, .is-correct) .opt-tag { grid-column: 2; justify-items: start; margin-left: 0; padding-left: 0; }
  .quiz-teaser.is-joined .opt:not(.is-picked):not(.is-correct) .opt-tag { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .quiz-teaser .opt, .quiz-teaser .opt::before, .teaser-go, .teaser-go::before { transition: none; }
}
@media (forced-colors: active) {
  /* high contrast drops the plate colours: the buttons get a border and the usual outline */
  .quiz-teaser .opt, .teaser-go { border: 1px solid ButtonText; }
  .quiz-teaser .opt:focus-visible, .teaser-go:focus-visible { outline: 2px solid Highlight; outline-offset: 3px; }
}

/* Quiz slide: the hero's neighbour to the right, with the same grid, frame and tabs. An answer in the hero moves
   the hero's content out to the left and the quiz in from the right; further down the page goes on as usual.
   Like the hero's card, the slide reads as a script: who speaks stands in a column on the left, each voice on a bar
   in its colour (the situation white, the AI orange, after the answer Alex's revision cyan). Then the question
   large, three plates in the slant of the bars, and the AI's praise and Alex's verdict, again with the speaker on
   the left. All ten questions share one grid cell, so the slide keeps its layout from question to question; nothing
   scrolls. */
.hero > .wrap, .quiz-show { transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1), opacity 0.45s ease; }
.quiz-show {
  --who: 4.25rem; --who-gap: 18px;
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  height: min(100%, calc(100dvh - 2 * var(--frame)));
  display: flex; flex-direction: column;
  padding: calc(var(--tab-d) + 8px) 0 calc(var(--tab-d) + 4px);
  transform: translateX(100%);
}
.quiz-show:focus { outline: none; }
.hero.quiz-shown { min-height: calc(100dvh - 2 * var(--frame)); }
/* also while the hero waits faded on the slides (it must not drift back in under the quiz) */
html main > section.hero.quiz-shown > .wrap, html.slides main > section.hero.quiz-shown > .wrap { transform: translateX(-100vw); }
.hero.quiz-shown > .quiz-show { transform: none; }
.hero.quiz-instant > .wrap, .hero.quiz-instant > .quiz-show { transition: none; }
.hero.quiz-instant .retro-grid { transition: none; }
/* the quiz has a look of its own: the horizon fades out, a flat grid seen from above lies behind the questions */
.retro-grid { transition: opacity 0.55s ease; }
.hero.quiz-shown .retro-grid { opacity: 0; }
.quiz-show::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: linear-gradient(rgba(var(--human-rgb), 0.07) 1px, transparent 1px), linear-gradient(90deg, rgba(var(--human-rgb), 0.07) 1px, transparent 1px);
  background-size: 48px 48px;
  background-position: center;
  -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000 30%, transparent 100%);
  mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000 30%, transparent 100%);
}
.quiz-show .review { flex: 1; min-height: 0; width: 100%; max-width: 1180px; margin: 0 auto; padding: clamp(8px, 2vh, 24px) clamp(16px, 3vw, 40px) clamp(12px, 2.5vh, 28px); display: flex; flex-direction: column; }
/* the slanted plates reach a few pixels past the card, so it does not clip */
.quiz-show .review-card.stage { flex: 1; min-height: 0; padding: 0; gap: 0; background: transparent; border: 0; overflow: visible; }
/* the head of the slide: "Zurück" on a plate on the left, the ladder of all ten on the right, ten small plates in
   the slant. A step turns cyan when the answer was right and amber when it was wrong; the current one is taller
   (and white while open). */
.stage-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: clamp(4px, 1.6vh, 24px); font-family: var(--font-body); font-size: var(--fs-m); font-weight: 400; line-height: var(--lh-snug); color: var(--muted); }
.stage .dots { flex: 0 1 440px; min-width: 0; gap: 8px; }
.stage .dot { flex: 1 1 0; min-width: 14px; width: auto; height: 28px; }
.stage .dot::before { width: 100%; height: 10px; border-radius: 0; background: rgba(var(--human-rgb), 0.22); transform: skewX(-13deg); transition: background-color 0.2s ease, height 0.2s ease; }
.stage .dot:hover::before { background: rgba(var(--human-rgb), 0.5); }
.stage .dot.is-right::before { background: var(--accent); }
.stage .dot.is-wrong::before { background: var(--amber); }
.stage .dot[aria-current="true"]::before { height: 16px; transform: skewX(-13deg); }
.stage .dot[aria-current="true"]:not(.is-right):not(.is-wrong)::before { background: var(--fg); }
.stage .dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.quiz-show .stage-body { flex: 1; min-height: 0; display: grid; overflow-y: auto; }
/* all questions share three rows (case, question with answers, the two voices), each as high as its tallest
   occupant: the case, the answers and the voices keep their places from question to question, and the block
   sits in the middle of the slide */
.quiz-show .track { min-height: 100%; grid-template-rows: auto auto auto; align-content: center; row-gap: clamp(12px, 2.8vh, 32px); }
/* safe: when the question is taller than the box (phones, held sideways) it starts at the top and scrolls, instead of
   spilling over the top edge, where no scrolling reaches it */
.quiz-show .track { align-content: safe center; }
.quiz-show .stage .slide { grid-area: auto; grid-row: 1 / span 3; grid-column: 1; display: grid; grid-template-rows: subgrid; }
.quiz-show .quiz { justify-content: flex-end; }
/* room for the focus ring and the slanted plates, which the scroll box would otherwise cut off; the box never
   scrolls sideways (the hidden focus ring still counts as content and showed a scrollbar) */
.quiz-show .stage-body { --edge: 20px; padding: 6px var(--edge); margin: -6px calc(-1 * var(--edge)); overflow-x: hidden; }
.quiz-show .stage .quiz-score { inset: 6px var(--edge); }
.quiz-show .slide { gap: clamp(12px, 2.8vh, 32px); }
/* the case: who speaks on the left, the lines on bars beside it */
.quiz-show .case > .hunk { display: grid; grid-template-columns: var(--who) minmax(0, 1fr); column-gap: var(--who-gap); row-gap: 6px; padding: 0; align-items: baseline; align-content: start; }
.quiz-show .case-who { grid-column: 1; font-size: var(--fs-m); }
.quiz-show .case-who.is-you { color: var(--accent); }
.quiz-show .case-say { grid-column: 2; font-size: var(--fs-l); line-height: 1.85; }
.quiz-show .case-say.is-you .bar { --mark: var(--accent); }
.quiz-show .case-say mark { background: none; color: inherit; font-weight: 600; }
/* real code: mono on a dark plate in the slant of the bars, what Alex changed on small cyan bars */
.quiz-show .case .code { grid-column: 2; justify-self: start; max-width: 100%; position: relative; isolation: isolate; padding: 14px 34px; font-size: var(--fs-m); line-height: 1.6; }
.quiz-show .case .code::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--plate); transform: skewX(-13deg); }
.quiz-show .code mark { padding: 0.04em 0.32em 0.08em; color: var(--bar-fg);
  background: linear-gradient(103deg, transparent calc(0.2em - 0.5px), var(--accent) calc(0.2em + 0.5px), var(--accent) calc(100% - 0.2em - 0.5px), transparent calc(100% - 0.2em + 0.5px)); }
/* the question and its answers on the line of the bars */
.quiz-show .quiz { gap: clamp(14px, 2.6vh, 24px); padding-left: calc(var(--who) + var(--who-gap)); }
.quiz-show .quiz-q {
  font-family: var(--font-display); font-weight: 500; font-size: min(var(--fs-xl), 6.2vh);
  line-height: var(--lh-tight); letter-spacing: var(--ls-display); text-wrap: balance;
}
.quiz-show .quiz-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 24px; }
/* plates like the hero's: the button keeps its rectangle for the pointer, a layer behind it draws the plate.
   Skewed by 13 degrees (the slant of the bars) instead of clipped, so the angle holds at any height and an
   answer may wrap onto a second line */
.quiz-show .opt, .stage-back, .stage-next { --plate-c: var(--plate); position: relative; isolation: isolate; border: 0; border-radius: 0; background: none; }
.quiz-show .opt::before, .stage-back::before, .stage-next::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--plate-c); transform: skewX(-13deg); transition: background-color 0.15s ease; }
/* keyboard focus: a 2px frame in the same slant, 3px off the plate */
.quiz-show .opt::after, .stage-back::after, .stage-next::after { content: ""; position: absolute; inset: -5px; z-index: -1; border: 2px solid var(--accent); transform: skewX(-13deg); visibility: hidden; pointer-events: none; }
.quiz-show .opt:focus-visible, .stage-back:focus-visible, .stage-next:focus-visible { outline: none; }
.quiz-show .opt:focus-visible::after, .stage-back:focus-visible::after, .stage-next:focus-visible::after { visibility: visible; }
.quiz-show .opt { gap: 14px; min-height: 60px; padding: 10px 22px 10px 24px; font-family: var(--font-display); font-weight: 500; font-size: clamp(1.05rem, 0.9rem + 0.45vw, 1.375rem); text-wrap: balance; transition: color 0.15s ease, opacity 0.15s ease, transform 0.12s ease; }
.quiz-show .opt-key { width: auto; height: auto; min-width: 1em; background: none; border-radius: 0; font-family: var(--font-display); font-size: var(--fs-s); font-weight: 600; color: var(--human); }
/* hover and focus white, your pick amber, the right one cyan */
.quiz-show .slide:not(.answered) .opt:hover:not(:disabled), .quiz-show .opt:focus-visible, .quiz-show .slide:not(.answered) .opt.is-picked { --plate-c: var(--bar); color: var(--bar-fg); }
.quiz-show .answered .opt.is-correct { --plate-c: var(--accent); color: var(--bar-fg); }
.quiz-show .answered .opt.is-picked:not(.is-correct) { --plate-c: var(--amber); color: var(--bar-fg); }
.quiz-show .slide:not(.answered) .opt:hover:not(:disabled) .opt-key, .quiz-show .opt:focus-visible .opt-key,
.quiz-show .opt.is-picked .opt-key, .quiz-show .opt.is-correct .opt-key { background: none; color: inherit; }
/* the word for your pick and for the right one stands under the plate, in its colour */
.quiz-show .opt-tag { position: absolute; left: 24px; top: calc(100% + 8px); margin: 0; padding: 0; justify-items: start; }
.quiz-show .opt.is-correct .opt-tag { color: var(--accent); }
.quiz-show .opt.is-picked:not(.is-correct) .opt-tag { color: var(--amber); }
/* the AI and Alex speak below the answers, like the case: the names in the column on the left, the AI in orange,
   Alex's verdict on a bar in the colour of the answer */
.quiz-show .stage-foot { margin-top: 0; padding-top: 0; font-size: var(--fs-l); line-height: var(--lh-snug); }
.quiz-show .stage-result { gap: clamp(8px, 1.4vh, 14px); }
.quiz-show .ai-reply, .quiz-show .stage.quiz-on .slide .comment p { display: grid; grid-template-columns: var(--who) minmax(0, 1fr); column-gap: var(--who-gap); align-items: baseline; margin: 0; }
.quiz-show .ai-reply { color: var(--ai); }
.quiz-show .avatar-ai, .quiz-show .who { display: block; width: auto; height: auto; padding: 0; border: 0; border-radius: 0; background: none; font-family: var(--font-body); font-size: var(--fs-m); font-weight: 600; line-height: inherit; }
.quiz-show .avatar-ai { color: var(--ai); }
.quiz-show .who { color: var(--accent); }
.quiz-show .ai-say, .quiz-show .say { font-family: var(--font-display); font-weight: 500; }
.quiz-show .verdict-box { --mark: var(--accent); justify-items: center; margin-right: 0.45em; padding: 0.1em 0.6em 0.14em; color: var(--bar-fg);
  background: linear-gradient(103deg, transparent calc(0.35em - 0.5px), var(--mark) calc(0.35em + 0.5px), var(--mark) calc(100% - 0.35em - 0.5px), transparent calc(100% - 0.35em + 0.5px)); }
.quiz-show .verdict-box:has(.verdict.is-wrong) { --mark: var(--amber); }
.quiz-show .verdict-box .verdict { color: inherit; }
.quiz-show .stage-row { align-items: center; gap: 28px; }
/* the reveal plays in beats, like a quiz show, instead of all at once: the plates take their colours, the AI's code
   gives way to Alex's, the words come up under the plates, then Alex's verdict with the way on. Each part fades in
   place, so nothing moves */
.quiz-show .stage-result { opacity: 0; transition: opacity 0.25s ease, visibility 0s linear 0.25s; }
.quiz-show .stage .answering .stage-result, .quiz-show .stage .answered .stage-result { opacity: 1; transition: opacity 0.25s ease, visibility 0s; }
.quiz-show .answered .opt { transition: color 0.35s ease, opacity 0.35s ease, transform 0.12s ease; }
.quiz-show .answered .opt::before { transition: background-color 0.35s ease; }
.quiz-show .stage.quiz-on .slide .hunk-fix { transform: translateY(6px); }
.quiz-show .stage.quiz-on .slide.answered .hunk-ai { transition: opacity 0.25s ease, visibility 0s linear 0.25s; }
.quiz-show .stage.quiz-on .slide.answered .hunk-fix { transform: none; transition: opacity 0.4s ease 0.1s, transform 0.4s ease 0.1s, visibility 0s linear 0.1s; }
.quiz-show .stage .opt-tag > span { opacity: 0; transform: translateY(-4px); transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s; }
.quiz-show .stage .answered .opt.is-correct [data-i18n="quiz.right"], .quiz-show .stage .answered .opt.is-picked:not(.is-correct) [data-i18n="quiz.pick"] { opacity: 1; transform: none; transition: opacity 0.3s ease 0.35s, transform 0.3s ease 0.35s, visibility 0s linear 0.35s; }
/* the way on is there for the keyboard at once (the focus moves to it), it only shows a beat later */
.quiz-show .stage-row { opacity: 0; transform: translateY(8px); transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s; }
.quiz-show .stage .answered .stage-row { opacity: 1; transform: none; transition: opacity 0.4s ease 0.55s, transform 0.4s ease 0.55s, visibility 0s; }
/* the bonus question shows "Ergebnis" before it is answered (below), so its row is there from the start */
.quiz-show .quiz-done .slide.is-current[data-cta]:not(.answered) .stage-row { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .quiz-show .stage-result, .quiz-show .stage .answering .stage-result, .quiz-show .stage .answered .stage-result,
  .quiz-show .answered .opt, .quiz-show .answered .opt::before,
  .quiz-show .stage.quiz-on .slide.answered .hunk-ai, .quiz-show .stage.quiz-on .slide.answered .hunk-fix,
  .quiz-show .stage .opt-tag > span, .quiz-show .stage .answered .opt.is-correct [data-i18n="quiz.right"], .quiz-show .stage .answered .opt.is-picked:not(.is-correct) [data-i18n="quiz.pick"],
  .quiz-show .stage-row, .quiz-show .stage .answered .stage-row { transition: none; }
  .quiz-show .stage.quiz-on .slide .hunk-fix, .quiz-show .stage-row { transform: none; }
}
/* "Zurück" on a dark plate, the way on on a white one */
.stage-back, .stage-next { min-height: 48px; padding: 0 28px; font-family: var(--font-display); font-size: var(--fs-m); font-weight: 500; line-height: var(--lh-snug); white-space: nowrap; cursor: pointer; transition: transform 0.12s ease; }
.stage-back { flex: none; color: var(--fg); }
.stage-back:hover { --plate-c: var(--bar); color: var(--bar-fg); }
.stage-next { --plate-c: var(--bar); color: var(--bar-fg); }
.stage-next:hover { --plate-c: var(--white); }
.stage-back:active, .stage-next:active { transform: scale(0.985); }
/* the bonus question can be left before it is answered: "Ergebnis" waits on a dark plate, like "Zurück", and turns
   white once the bonus is answered */
.quiz-done .slide.is-current[data-cta]:not(.answered) .stage-next { visibility: visible; --plate-c: var(--plate); color: var(--fg); }
.quiz-done .slide.is-current[data-cta]:not(.answered) .stage-next:hover { --plate-c: var(--bar); color: var(--bar-fg); }
/* the result takes the questions' place: "Ergebnis" on a bar, two big numbers, Alex's line, two ways on as plates
   (the bonus white) */
.stage .quiz-score { inset: 0; display: flex; flex-direction: column; justify-content: center; gap: clamp(20px, 4vh, 40px); overflow: visible; background: transparent; }
.score-label { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: var(--fs-l); }
.score-nums { display: flex; flex-wrap: wrap; gap: 12px clamp(40px, 7vw, 120px); }
.score-num { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.score-n { font-family: var(--font-display); font-weight: 500; font-size: var(--fs-xxl); line-height: var(--lh-tight); letter-spacing: var(--ls-display); font-variant-numeric: tabular-nums; }
.score-you .score-n { color: var(--accent); }
.score-ai .score-n { color: var(--amber); }
.score-k { color: var(--muted); font-size: var(--fs-m); }
.score-text { margin: 0; max-width: 46ch; font-family: var(--font-display); font-weight: 500; font-size: var(--fs-l); line-height: var(--lh-snug); }
.score-text b { font-weight: 600; color: var(--accent); }
.stage .quiz-score .quiz-opts { display: flex; flex-direction: row; flex-wrap: wrap; gap: 14px 22px; margin-top: 0; }
.quiz-show .quiz-score .opt { width: auto; min-height: 56px; padding: 0 30px 0 28px; }
.quiz-show .quiz-score .quiz-bonus { --plate-c: var(--bar); color: var(--bar-fg); }
.quiz-show .quiz-score .quiz-bonus:hover { --plate-c: var(--white); }
.quiz-show .quiz-score .quiz-bonus .opt-key { background: none; color: inherit; }
/* phones: answers one below the other with their word inside the plate, the names in a narrower column, the
   way on gets a row of its own */
@media (max-width: 700px) {
  .quiz-show { --who: 2.75rem; --who-gap: 12px; }
  .quiz-show .stage-body { --edge: 15px; }
  .quiz-show .review { padding-bottom: 6px; }
  .quiz-show .stage-result { gap: 6px; }
  .quiz-show .track, .quiz-show .slide { row-gap: 10px; }
  /* each question keeps its own rows, so a short code block leaves no hole above the question */
  .quiz-show .stage .slide { grid-template-rows: none; align-content: start; }
  /* the AI's draft and the fix share one place, as high as the taller one, so the question does not move on the
     answer; both sit on the question, so the room left over is above the code */
  .quiz-show .case > .hunk { align-self: end; }
  .quiz-show .quiz { gap: 12px; padding-left: 0; margin-top: 4px; }
  .quiz-show .quiz-opts { grid-template-columns: minmax(0, 1fr); gap: 6px; margin-bottom: 0; }
  .quiz-show .quiz-q { font-size: 1.625rem; }
  .quiz-show .case-who { font-size: var(--fs-s); }
  .quiz-show .case-say { font-size: var(--fs-m); line-height: 1.55; }
  .quiz-show .case .code { font-size: var(--fs-s); padding: 10px 24px; }
  .quiz-show .opt { gap: 10px; min-height: 44px; padding: 4px 20px 4px 16px; font-size: var(--fs-m); line-height: 1.3; }
  .quiz-show .opt-tag { position: static; margin-left: auto; padding-left: 8px; justify-items: end; }
  .quiz-show .opt.is-correct .opt-tag, .quiz-show .opt.is-picked:not(.is-correct) .opt-tag { color: inherit; }
  .quiz-show .stage-foot { font-size: var(--fs-m); }
  .quiz-show .avatar-ai, .quiz-show .who { font-size: var(--fs-s); }
  /* "Zurück" and the ladder share one row */
  .stage-head { gap: 16px; }
  .stage .dots { flex: 1 1 auto; gap: 5px; }
  .stage .dot { min-width: 10px; }
  .quiz-show .stage-row { flex-wrap: wrap; gap: 8px; }
  .quiz-show .stage.quiz-on .slide .stage-row > .comment { flex-basis: 100%; }
  .quiz-show .stage-next { flex: 1 1 auto; }
  .stage-back, .stage-next { min-height: 44px; padding: 0 20px; }
  .quiz-show .quiz-score .opt { min-height: 50px; }
}
/* small laptops and phones: a lower head, so the question still fits one screen */
@media (max-height: 700px) {
  .quiz-show .review { padding-top: 8px; }
  .stage-head { margin-bottom: 4px; }
  .stage-back { min-height: 38px; padding: 0 20px; }
}
/* low windows (phones held sideways): everything a size smaller; what still does not fit scrolls inside */
@media (max-height: 520px) {
  .quiz-show .review { padding-top: 4px; padding-bottom: 12px; }
  .quiz-show .slide, .quiz-show .track { gap: 8px; }
  .quiz-show .stage-result { gap: 2px; }
  .quiz-show .quiz { gap: 8px; }
  .quiz-show .quiz-q { font-size: 1.5rem; }
  .quiz-show .case-say { font-size: var(--fs-m); line-height: 1.7; }
  .quiz-show .case .code { font-size: var(--fs-s); padding-block: 8px; }
  .quiz-show .opt { min-height: 44px; padding-block: 6px; font-size: var(--fs-m); }
  .quiz-show .stage-foot { font-size: var(--fs-s); line-height: 1.4; }
  .stage-head { margin-bottom: 2px; }
  .stage .dot { height: 20px; }
  .stage-next { min-height: 40px; }
  .score-n { font-size: 3rem; }
}
@media (prefers-reduced-motion: reduce) { .hero > .wrap, .quiz-show, .retro-grid, .stage .dot::before, .quiz-show .opt::before, .stage-back::before, .stage-next::before { transition: none; } }
@media (forced-colors: active) {
  /* high contrast drops the plates: the buttons get a border and the usual outline */
  .quiz-show .opt, .stage-back, .stage-next { border: 1px solid ButtonText; }
  .quiz-show .opt:focus-visible, .stage-back:focus-visible, .stage-next:focus-visible { outline: 2px solid Highlight; outline-offset: 3px; }
}

/* Finale: "you decide what happens next" as a dark terminal band */
.next-band { background: var(--term-bg); color: var(--term-fg); }
.next-band .statement h2 { color: var(--term-fg); }
.next-band .bar { --mark: var(--term-fg); color: var(--term-bg); }
.section.next-band { overflow: hidden; }
.section.next-band:last-child .wrap { padding-bottom: clamp(40px, 5vw, 64px); }
.next-band :focus-visible { outline-color: var(--term-accent); }

/* Mini terminal: one font, one size, like a real console */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.cli-wrap { max-width: none; }
@media (min-width: 900px) { .cli-screen { height: 380px; } }
.cli {
  background: var(--term-surface);
  border: 1px solid var(--term-line);
  border-radius: 8px;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: var(--fs-m);
  line-height: var(--lh-body);
  color: var(--term-fg);
  cursor: text;
  transition: border-color 0.15s ease;
}
.cli:focus-within { border-color: rgba(var(--human-rgb), 0.45); }
.cli-head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  padding: 0 14px;
  border-bottom: 1px solid var(--term-line);
  background: rgba(var(--white-rgb), 0.02);
}
.cli-dots { position: absolute; left: 14px; display: flex; gap: 7px; }
/* the three window buttons in the colours of a Mac */
.cli-dots i { display: block; width: 10px; height: 10px; border-radius: 50%; background: var(--win-close); }
.cli-dots i:nth-child(2) { background: var(--win-min); }
.cli-dots i:nth-child(3) { background: var(--win-max); }
.cli-title { font-family: var(--font-body); font-size: var(--fs-s); color: var(--term-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 40px; }
.cli-screen {
  height: 300px;
  overflow-y: auto;
  padding: 12px 14px;
  scrollbar-width: thin;
  scrollbar-color: var(--term-line) transparent;
}
.cli-out { display: block; font: inherit; }
.cli-prompt samp { font: inherit; }
.cli-line { white-space: pre-wrap; overflow-wrap: anywhere; }
.cli-line .p { color: var(--term-accent); }
.cli-line.muted, .cli-line .muted { color: var(--term-muted); }
.cli-line.accent, .cli-line.err { color: var(--term-accent); }
.cli-line .ok { color: var(--ok); }
/* `help` in a narrow terminal: the command bright, its description a size smaller and grey beneath it */
.cli-line.help-cmd { margin-top: 6px; }
/* the commands in `help` run when clicked; they look like the text they are until a pointer or focus finds them */
.cli-cmd { padding: 0; border: 0; background: none; color: var(--term-fg); font: inherit; cursor: pointer; text-decoration: underline; text-decoration-color: rgba(var(--white-rgb), 0.25); text-underline-offset: 3px; }
.cli-cmd:hover, .cli-cmd:focus-visible { color: var(--term-accent); text-decoration-color: currentColor; }
.cli-line.help-desc { padding-left: 4ch; font-size: var(--fs-s); line-height: var(--lh-snug); }
.cli-line.chat-in .who { color: var(--term-accent); }
/* the greeting offers three commands to click, for those who would not know what to type */
.cli-try { margin-bottom: 8px; }
.cli-chip { min-height: 28px; margin: 2px 2px 2px 4px; padding: 0 10px; border: 0; border-radius: 4px; background: rgba(var(--white-rgb), 0.07); color: var(--term-fg); font: inherit; cursor: pointer; transition: background-color 0.15s ease; }
.cli-chip:hover { background: rgba(var(--white-rgb), 0.14); }
/* Live chat: a movable chat window; the header is the drag handle */
.chat-open svg { width: 18px; height: 18px; }
.chatw {
  position: fixed;
  inset: auto calc(var(--frame) + 16px) calc(var(--frame) + 16px) auto;
  z-index: 70; /* above the snow (50), the bug (60) and the frame (65), below the game (100) */
  width: 380px;
  max-width: calc(100vw - 2 * var(--frame) - 32px);
  height: min(540px, calc(100dvh - 2 * var(--frame) - 48px));
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  overflow: visible;
}
.chatw-win {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 24px 64px rgba(var(--black-rgb), 0.3), 0 2px 10px rgba(var(--black-rgb), 0.12);
  font-family: var(--font-body);
}
.chatw-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 10px 10px 16px;
  border-bottom: 1px solid var(--line);
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.chatw-head.dragging { cursor: grabbing; }
.chatw-status { flex: 1; min-width: 0; margin: 0; display: flex; align-items: center; gap: 8px; font-family: var(--font-display); font-weight: 600; font-size: var(--fs-m); line-height: var(--lh-snug); color: var(--fg); }
.chatw-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--status-wait); }
.chatw-status[data-state="online"] .chatw-dot { background: var(--status-online); }
.chatw-status[data-state="offline"] .chatw-dot { background: var(--status-offline); }
.chatw-close {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
@media (hover: hover) { .chatw-close:hover { color: var(--fg); background: var(--surface); } }
.chatw-close:focus-visible { color: var(--fg); }
.chatw-close svg { width: 18px; height: 18px; }
.chatw-min { margin-right: -8px; }
.chatw-dock svg { transition: transform 0.2s ease; }
.chatw-dock[data-next="bl"] svg { transform: rotate(90deg); }
.chatw-dock[data-next="tl"] svg { transform: rotate(180deg); }
.chatw-dock[data-next="tr"] svg { transform: rotate(-90deg); }
.chatw.snapping { transition: left 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), top 0.3s cubic-bezier(0.2, 0.8, 0.2, 1); }
@media (max-width: 560px) { .chatw-dock { display: none; } }
@media (prefers-reduced-motion: reduce) { .chatw-dock svg, .chatw.snapping { transition: none; } }
.chatw-min .ico-max, .chatw.min .chatw-min .ico-min { display: none; }
.chatw.min .chatw-min .ico-max { display: inline; }
.chatw-unread {
  flex: none;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  display: inline-grid;
  place-items: center;
  border-radius: 10px;
  background: var(--accent);
  color: var(--bar-fg);
  font-family: var(--font-body);
  font-size: var(--fs-s);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.chatw-unread[hidden] { display: none; }
/* collapsed: only the title bar stays, wherever the window was */
.chatw.min, .chatw.min .chatw-win { height: auto; }
.chatw.min .chatw-log, .chatw.min .chatw-in { display: none; }
.chatw.min .chatw-head { border-bottom: 0; }
.chatw-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px 16px;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.cnote { margin: 0; font-size: var(--fs-s); line-height: var(--lh-body); color: var(--muted); }
.cnote.err { color: var(--accent); }
.cnote a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.cnote a:hover { text-decoration-thickness: 2px; }
/* messages as a thread, like the comments elsewhere on the page */
.cmsg { display: flex; gap: 12px; align-items: flex-start; }
.cmsg-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cmsg-meta { margin: 0; display: flex; align-items: baseline; gap: 8px; font-size: var(--fs-s); }
.cmsg-time { font-size: var(--fs-s); color: var(--muted); font-variant-numeric: tabular-nums; }
.cmsg-text { margin: 0; font-size: var(--fs-m); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; }
.chatw-in {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin: 0 12px 12px;
  /* the send key keeps the same gap to the field's edge on the right as above and below a single line */
  --send-gap: calc(4px + max(0px, calc((var(--fs-m) * var(--lh-body) + 18px - 38px) / 2)));
  padding: 4px var(--send-gap) 4px 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
}
.chatw-in:focus-within { border-color: var(--accent); }
.chatw-in textarea {
  flex: 1;
  min-width: 0;
  max-height: 120px;
  padding: 9px 0;
  border: 0;
  outline: 0;
  resize: none;
  background: transparent;
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-m);
  line-height: var(--lh-body);
}
.chatw-in textarea::placeholder { color: var(--muted); }
.chatw-send {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: var(--accent);
  color: var(--bar-fg);
  cursor: pointer;
  /* centred on a single line of text; once the text grows to more lines it stays at the bottom */
  margin-bottom: calc(var(--send-gap) - 4px);
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
/* nothing typed yet: a quiet grey key instead of a washed-out accent block */
.chatw-send:disabled { background: var(--surface); color: var(--muted); cursor: default; }
.chatw-send:not(:disabled):active { transform: scale(0.94); }
.chatw-send svg { width: 18px; height: 18px; }
/* variant b: light/dark like the page, no colour band, quiet bubbles */
.chatw[data-v="b"] .chatw-prompt, .chatw[data-v="b"] .chatw-title { display: none; }
.chatw[data-v="b"] .cmsg { max-width: 82%; }
.chatw[data-v="b"] .cmsg-out { align-self: flex-end; }
.chatw[data-v="b"] .cmsg-out .cmsg-meta { justify-content: flex-end; }
.chatw[data-v="b"] .cmsg-body { width: 100%; }
.chatw[data-v="b"] .cmsg-meta { order: 2; padding: 0 4px; }
.chatw[data-v="b"] .cmsg-text { padding: 10px 14px; border-radius: 14px; background: var(--surface); }
.chatw[data-v="b"] .cmsg-in .cmsg-text { border-bottom-left-radius: 4px; }
.chatw[data-v="b"] .cmsg-out .cmsg-text { background: var(--bar); color: var(--bar-fg); border-bottom-right-radius: 4px; }
.chatw[data-v="b"] .chatw-log { gap: 10px; }
@media (max-width: 560px) {
  .chatw { inset: auto calc(var(--frame) + 4px) calc(var(--frame) + 4px) calc(var(--frame) + 4px); width: auto; max-width: none; height: min(560px, calc(100dvh - 2 * var(--frame) - 8px)); }
  .chatw-head { cursor: default; }
}
@media (prefers-reduced-motion: reduce) { .chatw-send { transition: none; } }
.cli-art {
  margin: 0;
  font-family: inherit;
  font-size: inherit;
  line-height: var(--lh-tight);
  color: var(--term-fg);
  white-space: pre;
  overflow: hidden;
}
.cli-art .r { color: var(--term-fg); }
.cli-art .f { color: var(--ai); }
.cli-art .s, .cli-art .m { color: var(--term-muted); }
.cli-art .g { color: var(--term-accent); }
.cli-hm { margin: 4px 0 6px; line-height: var(--lh-snug); overflow-x: auto; }
.cli-in { display: flex; align-items: center; margin: 0; }
.cli-prompt { flex: none; margin-right: 1ch; color: var(--term-muted); white-space: pre; }
.cli-prompt .host { color: var(--term-accent); }
.cli-field { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; }
.cli-in input {
  width: calc((var(--len, 0) + 1) * 1ch);
  min-width: 1ch;
  max-width: 100%;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--term-fg);
  caret-color: var(--term-accent);
  font-family: var(--font-mono);
  font-size: inherit;
  line-height: inherit;
}
.cli-block {
  display: inline-block;
  width: 1ch;
  height: 1.15em;
  margin-left: -1ch;
  background: var(--term-accent);
  animation: blink 1.1s steps(1) infinite;
  pointer-events: none;
}
.cli:focus-within .cli-block { display: none; }
@media (max-width: 480px) {
  .cli-screen { height: 280px; }
}
@media (prefers-reduced-motion: reduce) { .cli, .cli-chip { transition: none; } .cli-block { animation: none; } }

/* Hidden command `smart`: the page compressed to its minimum */
html.smart main, html.smart .site-foot, html.smart .nav { display: none !important; }
.smart-view { min-height: calc(100vh - 65px); display: grid; align-items: center; background: var(--bg); }
.smart-inner { padding-block: clamp(48px, 8vw, 96px); display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
.smart-core { display: flex; flex-direction: column; align-items: flex-start; gap: 18px; }
.smart-view h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-xxl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
}
.smart-role { margin: 0; font-size: var(--fs-l); color: var(--fg); }
.smart-line { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: var(--fs-l); }
.smart-links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 6px; }
.smart-stats { margin: 8px 0 0; font-size: var(--fs-s); color: var(--muted); font-variant-numeric: tabular-nums; }
.smart-back {
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--fg);
  font-size: var(--fs-m);
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}
.smart-back:hover { color: var(--accent); }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.55s; }

/* Hidden command `bug`: a pixel bug crawls through the page and eats the letters */
.bug-sprite { position: absolute; left: 0; top: 0; z-index: 60; pointer-events: none; transition: transform 70ms linear; will-change: transform; }
.bug-sprite svg { position: absolute; inset: 0; width: 100%; height: 100%; shape-rendering: crispEdges; }
.bug-sprite .f2 { visibility: hidden; }
.bug-sprite.walk .f1 { animation: bug-a 0.24s steps(1) infinite; }
.bug-sprite.walk .f2 { animation: bug-b 0.24s steps(1) infinite; }
@keyframes bug-a { 0%, 49.9% { visibility: visible; } 50%, 100% { visibility: hidden; } }
@keyframes bug-b { 0%, 49.9% { visibility: hidden; } 50%, 100% { visibility: visible; } }
.bug-w .eaten { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .bug-sprite { transition: none; } .bug-sprite.walk .f1, .bug-sprite.walk .f2 { animation: none; } }

/* Hidden command `snow`: snowfall over the whole page */
.snow { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 50; }

/* Secret game: LIGHTRACE (fixed look, always dark) */
.game {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding:
    max(12px, env(safe-area-inset-top, 0px))
    max(12px, env(safe-area-inset-right, 0px))
    max(12px, env(safe-area-inset-bottom, 0px))
    max(12px, env(safe-area-inset-left, 0px));
  background: var(--stage-bg);
  color: var(--stage-fg);
  font-family: var(--font-mono);
  color-scheme: dark;
}
.game:focus { outline: none; }
.game-hud { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.game-title {
  margin: 0;
  font-weight: 500;
  letter-spacing: var(--ls-caps-wide);
  color: var(--neon-light);
  text-shadow: 0 0 10px rgba(var(--human-rgb), 0.8);
}
.game-score { margin: 0; display: flex; align-items: baseline; gap: 10px; font-size: var(--fs-s); }
.game-score b { font-weight: 500; font-size: var(--fs-l); font-variant-numeric: tabular-nums; }
.game-score .you { color: var(--neon-light); }
.game-score .ai { color: var(--ai); }
.game-close, .game-pad button {
  font: inherit;
  color: var(--stage-fg);
  background: transparent;
  border: 1px solid rgba(var(--human-rgb), 0.5);
  border-radius: 6px;
  box-shadow: 0 0 10px rgba(var(--human-rgb), 0.15);
  cursor: pointer;
}
.game-close { min-height: 40px; padding: 0 14px; }
.game-close:hover, .game-pad button:hover { border-color: rgba(var(--human-rgb), 1); background: rgba(var(--human-rgb), 0.1); }
.game-close:focus-visible, .game-pad button:focus-visible { outline: 2px solid var(--neon-light); outline-offset: 2px; }
.game-stage { position: relative; flex: 1; min-height: 0; display: grid; place-items: center; touch-action: none; }
.game-canvas {
  display: block;
  max-width: 100%;
  max-height: 100%;
  border: 1px solid rgba(var(--human-rgb), 0.35);
  box-shadow: 0 0 30px rgba(var(--human-rgb), 0.15);
}
.game-msg {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 16px;
  text-align: center;
  white-space: pre-line;
  pointer-events: none;
  font-size: clamp(1rem, 0.8rem + 1.2vw, 1.5rem);
  line-height: var(--lh-body);
  text-shadow: 0 0 12px rgba(var(--human-rgb), 0.7), 0 0 2px var(--stage-bg);
}
.game-help { margin: 0; text-align: center; font-size: var(--fs-s); color: var(--stage-dim); }
.game-pad { display: none; grid-template-columns: repeat(3, 60px); grid-template-rows: repeat(2, 60px); gap: 8px; justify-content: center; }
.game-pad button { display: grid; place-items: center; }
.game-pad svg { width: 24px; height: 24px; }
.game-pad [data-dir="up"] { grid-column: 2; grid-row: 1; }
.game-pad [data-dir="left"] { grid-column: 1; grid-row: 2; }
.game-pad [data-dir="down"] { grid-column: 2; grid-row: 2; }
.game-pad [data-dir="right"] { grid-column: 3; grid-row: 2; }
@media (pointer: coarse) { .game-pad { display: grid; } }
/* phones held sideways: the pad goes beside the field, which keeps the height; the keyboard hint is not needed there */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 560px) {
  .game { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto minmax(0, 1fr); column-gap: 16px; }
  .game-hud { grid-column: 1 / -1; }
  .game-help { display: none; }
  .game-pad { align-self: center; grid-template-columns: repeat(3, 52px); grid-template-rows: repeat(2, 52px); }
}
@media (prefers-reduced-motion: reduce) {
  .carousel, .opt { transition: none; }
}
.dots { display: flex; flex-wrap: nowrap; gap: 2px; min-width: 0; }
.dot {
  width: 24px;
  height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 1px;
  background: var(--line);
  transition: background-color 0.2s ease, transform 0.2s ease;
}
.dot:hover::before { background: var(--muted); }
.dot[aria-current="true"]::before { background: var(--fg); transform: scale(1.25); }
@media (prefers-reduced-motion: reduce) {
  .track, .dot::before { transition: none; }
}

/* Sections */
.section .wrap {
  padding-block: clamp(56px, 7vw, 100px);
  display: flex;
  flex-direction: column;
  gap: clamp(36px, 5vw, 56px);
}
.statement { display: flex; flex-direction: column; gap: 18px; }
.statement h2, .h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}
.statement .lede {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-l);
  text-wrap: balance;
}

/* Approach: three steps, each with its icon */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  --gap: clamp(28px, 4vw, 48px);
  --icon: 24px;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  max-width: 780px;
}
@media (min-width: 960px) {
  #approach .wrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(48px, 6vw, 96px); align-items: start; }
}
.steps li { position: relative; min-width: 0; display: flex; flex-direction: column; gap: 10px; padding-left: calc(var(--icon) + 18px); }
.steps h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-l);
  line-height: var(--lh-snug);
}
.steps p { margin: 0; color: var(--text); max-width: 52ch; }
/* the step texts are short and read at a glance: no word is broken across lines */
.steps p { -webkit-hyphens: manual; hyphens: manual; text-wrap: pretty; }
/* each step carries just its icon, centred on the first line of the heading: a lens, a spark for the AI, a check.
   White strokes without ring or line between them, so the three steps stay calm */
.steps li::before {
  content: "";
  position: absolute;
  top: calc(var(--fs-l) * 0.65 - var(--icon) / 2);
  left: 0;
  width: var(--icon);
  height: var(--icon);
  background: center / contain no-repeat;
}
.steps li:nth-child(1)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F2F0F1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E"); }
.steps li:nth-child(2)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F2F0F1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5l1.9 5.1L19 12l-5.1 1.9L12 19l-1.9-5.1L5 12l5.1-1.9z'/%3E%3C/svg%3E"); }
.steps li:nth-child(3)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F2F0F1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E"); }

/* About */
.about {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: center;
}
.about-band { background: var(--term-bg); color: var(--term-fg); }
/* the darker terminal bands fade in and out of the page ground: no hard edge between sections */
:root { --band-fade: clamp(96px, 12vw, 180px); }
/* "About me" and "Contact" look out of the same window as the hero: deep space, stars, the Moon and the Sun (drawn in
   app.js). Sky and planets fade in and out with the band, so the page ground stays calm between the sections */
.space-band { position: relative; overflow: hidden; color-scheme: dark; background: linear-gradient(to bottom, var(--page), var(--space) var(--band-fade), var(--space) calc(100% - var(--band-fade)), var(--page)); }
.space-band .wrap { position: relative; z-index: 1; }
/* Earth, Moon and Sun can be grabbed and turned sideways (app.js); upward swipes still scroll the page */
.hero, .space-band { touch-action: pan-y pinch-zoom; }
.can-grab { cursor: grab; }
.grabbing, .grabbing * { cursor: grabbing; user-select: none; }
.space-band > .retro-grid {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--band-fade), #000 calc(100% - var(--band-fade) * 0.6), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 var(--band-fade), #000 calc(100% - var(--band-fade) * 0.6), transparent);
}
/* the photo's backdrop (rgb 7) a touch deeper, down to the black of space, so no lighter disc shows behind the face */
.about-band .portrait { filter: contrast(1.04); }
#terminal.next-band { background: linear-gradient(to bottom, var(--page), var(--term-bg) var(--band-fade)); }
.about-band .h2 { color: var(--term-fg); }
.about-band .about-text p { color: var(--text); }
.prompt { font-family: var(--font-mono); font-size: var(--fs-s); color: var(--term-muted); margin: 0; }
.prompt .host { color: var(--term-accent); }
@keyframes blink { 50% { opacity: 0; } }
/* a calm portrait without a frame: the photo's dark backdrop fades into the band, so only the person stands out.
   contrast(0.97) lifts the photo's black to the band's black, so no darker patch shows behind the face */
.portrait {
  display: block;
  width: clamp(240px, 28vw, 400px);
  height: auto;
  aspect-ratio: 1;
  max-width: 100%;
  object-fit: cover;
  filter: contrast(0.97);
  -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 46%, #000 58%, transparent 100%);
  mask-image: radial-gradient(ellipse 50% 50% at 50% 46%, #000 58%, transparent 100%);
}
.about-text { display: flex; flex-direction: column; gap: 24px; min-width: 0; max-width: 64ch; }

.about-text p { margin: 0; max-width: 52ch; text-wrap: pretty; } /* the same measure as the steps, about 50 to 60 characters a line */
.placeholder { color: var(--muted); font-style: italic; }
@media (max-width: 640px) { .about { grid-template-columns: minmax(0, 1fr); } .about > .portrait { justify-self: center; } }

#approach .prompt, #contact .prompt { color: var(--muted); }
#approach .prompt .host, #contact .prompt .host { color: var(--accent); }

/* Entrance: parts rise in turn as they scroll in; the prompt's command types itself */
html.reveal-on .rv { opacity: 0; transform: translateY(24px); }
html.reveal-on .rv.in {
  opacity: 1;
  transform: none;
  transition: opacity 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) var(--d, 0ms), transform 0.75s cubic-bezier(0.2, 0.7, 0.2, 1) var(--d, 0ms);
}
html.reveal-on .prompt.rv .cmd { display: inline-block; clip-path: inset(0 100% 0 0); }
html.reveal-on .prompt.rv.in .cmd { animation: prompt-type calc(var(--n, 8) * 55ms) steps(var(--n, 8), end) calc(var(--d, 0ms) + 250ms) forwards; }
@keyframes prompt-type { to { clip-path: inset(0 0 0 0); } }
@media print {
  html.reveal-on .rv { opacity: 1 !important; transform: none !important; }
  html.reveal-on .prompt.rv .cmd { clip-path: none !important; }
}

/* Contact */
.contact-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.mail {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 18px;
  border: 1.5px solid var(--line);
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: var(--fs-m);
  user-select: all;
  max-width: 100%;
  overflow-wrap: anywhere;
}
.contact-block { display: flex; flex-direction: column; gap: 8px; }
/* Contact: primary button, chat, then the address as plain text: a click copies it */
.contact-row { gap: 12px 20px; }

/* Werkstatt: three experiments running on this page, each with a way straight in */
.ws-list { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(28px, 4vw, 48px); }
@media (min-width: 900px) { .ws-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.ws-list li { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding-top: 18px; }
.ws-list h3 { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: var(--fs-l); line-height: var(--lh-snug); }
.ws-list p { margin: 0 0 8px; color: var(--text); max-width: 52ch; }
/* Werkstatt: quiet text links with an arrow, not read aloud; the contact buttons keep the site's own style */
.ws-list .btn { margin-top: auto; min-height: 44px; padding: 0; gap: 8px; border-radius: 0; background: none; color: var(--fg); font-weight: 600; }
.ws-list .btn:hover { background: none; transform: none; }
.ws-list .btn span { text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 5px; text-decoration-thickness: 1px; transition: text-decoration-color 0.15s ease; }
.ws-list .btn:hover span { text-decoration-color: currentColor; }
.ws-list .btn::after { content: "→"; content: "→" / ""; font-weight: 500; transition: transform 0.15s ease; }
.ws-list .btn:hover::after { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) { .ws-list .btn span, .ws-list .btn::after { transition: none; } }
.ws-list .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* The frame: the page sits in a black screen border with rounded inner corners and two tabs */
:root {
  --frame: clamp(8px, 1.25vw, 18px);
  --frame-r: clamp(12px, 1.5vw, 22px);
  --tab-d: 30px;
  --frame-line: transparent; /* contour on the frame and tabs; was var(--menu-line) */
  --menu-line: rgba(var(--white-rgb), 0.16);
}
html { background: var(--frame-bg); scrollbar-color: var(--line) var(--frame-bg); }
body { padding: var(--frame); }
/* the last band runs down to the frame; its content clears the bottom tab */
main > .section:last-child .wrap { padding-bottom: calc(clamp(40px, 5vw, 64px) + var(--tab-d)); }
.site-head { top: var(--frame); }
section { scroll-margin-top: calc(72px + var(--frame)); }
/* one fixed layer for the frame, the tabs and the bottom icons: on phones the browser bar slides in and out,
   and pieces fixed separately would drift apart for a moment */
.chrome { position: fixed; inset: 0; z-index: 65; pointer-events: none; }
/* no clipping: the black reaches past the layer's edge while the browser bar is still moving */
.frame { position: absolute; inset: 0; pointer-events: none; }
.frame-hole {
  position: absolute;
  inset: var(--frame);
  border-radius: var(--frame-r);
  box-shadow: 0 0 0 100vmax var(--frame-bg), inset 0 0 0 1px var(--frame-line);
}
.ftab {
  position: absolute;
  left: 50%;
  z-index: 1;
  pointer-events: auto;
  height: var(--tab-d);
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateX(-50%);
  text-decoration: none;
  /* before the script has drawn the shape: a plain black tab */
  background: var(--frame-bg);
  border-radius: 0 0 10px 10px;
  padding-inline: 26px;
}
.ftab.drawn { background: none; border-radius: 0; padding-inline: 0; }
.ftab-top { top: var(--frame); align-items: flex-start; }
@media (min-width: 700px) { .ftab-top { position: fixed; } }
/* the name is the menu button; the tab grows into a drawer below it */
.ftab-name {
  appearance: none;
  height: var(--tab-d);
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.ftab-top.is-open .ftab-name, .ftab-name:hover { color: var(--term-accent); }
/* a small chevron after the name says there is a menu behind it; it turns over while the drawer is open */
.menu-caret { flex: none; width: 10px; height: 6px; margin-left: 6px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.28s ease; }
.ftab-name[aria-expanded="true"] .menu-caret { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .menu-caret { transition: none; } }
.menu-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--tab-d);
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  gap: 0;
  padding: 0 36px 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s ease, visibility 0s linear 0.16s;
}
.menu-panel[hidden] { display: none; }
.ftab-top.shown .menu-panel { opacity: 1; visibility: visible; transition: opacity 0.28s ease; }
.menu-nav { flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.menu-nav a, .menu-row a, .menu-row button {
  appearance: none;
  margin: 0;
  border: 0;
  background: none;
  font-family: var(--font-display);
  font-weight: 600;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s ease;
}
.menu-nav a { padding: 9px 14px; font-size: 1rem; letter-spacing: var(--ls-caps-wide); }
.menu-row { flex: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; }
.menu-row a, .menu-row button { padding: 6px 4px; font-size: var(--fs-s); letter-spacing: var(--ls-caps-wide); }
.menu-nav a:hover, .menu-row a:hover, .menu-row button:hover,
.menu-nav a:focus-visible, .menu-row a:focus-visible, .menu-row button:focus-visible { color: var(--fg); outline: none; }
.menu-nav a:focus-visible, .menu-row a:focus-visible, .menu-row button:focus-visible { text-decoration: underline; text-underline-offset: 5px; }
.lang-menu button[aria-pressed="true"] { color: var(--fg); }
/* the section in view, marked like the language in use */
.menu-nav a[aria-current] { color: var(--fg); -webkit-text-stroke: 0.5px currentColor; }
@media (prefers-reduced-motion: reduce) { .menu-panel, .ftab-top.shown .menu-panel { transition: none; } }
.ftab-bottom { bottom: var(--frame); border-radius: 10px 10px 0 0; }
.ftab-shape { position: absolute; left: 0; top: -2px; overflow: visible; display: none; }
/* while the page scrolls freely, text fades out before a tab instead of running under it */
html:not(.slides) .frame::before, html:not(.slides) .frame::after {
  content: '';
  position: absolute;
  left: var(--frame);
  right: var(--frame);
  height: calc(var(--tab-d) + 18px);
}
/* each fade takes the colour of the section scrolling under it (set by the script), so it never shows as a band of its own */
html:not(.slides) .frame::before { top: var(--frame); border-radius: var(--frame-r) var(--frame-r) 0 0; background: var(--fade-top, var(--term-bg)); -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent); mask-image: linear-gradient(to bottom, #000 45%, transparent); transition: background-color 0.3s ease, opacity 0.3s ease; }
html:not(.slides) .frame::after { bottom: var(--frame); border-radius: 0 0 var(--frame-r) var(--frame-r); background: var(--fade-bottom, var(--term-bg)); -webkit-mask-image: linear-gradient(to top, #000 45%, transparent); mask-image: linear-gradient(to top, #000 45%, transparent); transition: background-color 0.3s ease, opacity 0.3s ease; }
/* over the Earth there is no fade: the frame is a window, and the view runs right up to its edge */
html:not(.slides) .frame.space-top::before, html:not(.slides) .frame.space-bottom::after { opacity: 0; }
@media (prefers-reduced-motion: reduce) { html:not(.slides) .frame::before, html:not(.slides) .frame::after { transition: none; } }
.ftab.drawn .ftab-shape { display: block; }
.ftab-bottom .ftab-shape { top: auto; bottom: -2px; transform: scaleY(-1); }
.ftab-shape .ftab-fill { fill: var(--frame-bg); }
.ftab-shape .ftab-edge { fill: none; stroke: var(--frame-line); stroke-width: 1; }
.ftab-label {
  position: relative;
  font-family: var(--font-display);
  font-size: var(--fs-s);
  font-weight: 600;
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--fg);
  text-decoration: none;
}
.ftab-bottom .ftab-label { font-weight: 600; letter-spacing: var(--ls-caps); color: var(--muted); }
/* the tabs are slim; their buttons still take a finger: 44 px to tap, without looking bigger */
.ftab-name::after, .ftab-scroll::after { content: ''; position: absolute; left: -12px; right: -12px; top: 50%; height: 44px; transform: translateY(-50%); }
a.ftab:hover .ftab-label, .ftab-bottom .ftab-label:hover { color: var(--term-accent); }
a.ftab:focus-visible, .ftab-bottom .ftab-label:focus-visible { outline: none; }
a.ftab:focus-visible .ftab-label, .ftab-bottom .ftab-label:focus-visible { color: var(--term-accent); text-decoration: underline; text-underline-offset: 4px; }
/* small screens: the drawer keeps all its rows in view (the five languages on one line, the nav without scrolling
   on phones held sideways) */
@media (max-width: 360px) { .menu-row { column-gap: 12px; } }
@media (max-height: 500px) { .menu-nav a { padding-block: 4px; } }
@media (max-width: 480px) {
  :root { --tab-d: 26px; }
  .ftab-label { font-size: var(--fs-s); letter-spacing: var(--ls-caps); }
}
html.smart .ftab-bottom { display: none; }
/* bottom tab: "scroll down" until the page ends, then the copyright */
.ftab-swap { position: relative; display: grid; place-items: center; }
.ftab-swap > * { grid-area: 1 / 1; transition: opacity 0.3s ease, visibility 0s linear 0s; }
.ftab-scroll {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.ftab-bottom:not(.at-end) .ftab-copy, .ftab-bottom.at-end .ftab-scroll {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
@media (prefers-reduced-motion: reduce) {
  .ftab-swap > * { transition: none; }
}
/* The ladder at the left edge: a tab like the two in the frame, standing on its side (the same outline, turned),
   with one step per section, as in the menu. The steps are the page's grey, dimmed to half (still 3 : 1 on the black
   tab); the section in view is the same step, only bright. Hover or focus names a step, a click goes there. Only where the page leaves room for it: the text starts at the left gutter,
   and below 1360 px the tab would touch it (the menu does the same job there) */
.side-nav { position: absolute; top: calc(50% - 119px); top: round(calc(50% - 119px), 1px); left: calc(var(--frame) - 2px); left: round(down, calc(var(--frame) - 2px), 1px); width: 26px; height: 238px; display: none; }
@media (min-width: 1360px) { .side-nav { display: block; } }
html.smart .side-nav { display: none; }
.side-shape { position: absolute; inset: 0; overflow: visible; }
.side-shape path { fill: var(--frame-bg); }
/* the steps sit in the middle of the whole black, frame and tab together: the tab's face is frame + 24 px from the edge.
   Tab and steps land on whole pixels (round() where the browser has it), so the slim steps stay crisp */
.side-steps { position: absolute; left: calc(2px - var(--frame) / 2); left: round(calc(2px - var(--frame) / 2), 1px); top: 35px; width: 24px; display: flex; flex-direction: column; }
.side-steps a { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 28px; pointer-events: auto; text-decoration: none; }
.side-steps a::before { content: ''; width: 6px; height: 22px; border-radius: 3px; background: var(--muted); opacity: 0.5; transition: opacity 0.2s ease, background-color 0.2s ease; }
.side-steps a:hover::before { opacity: 1; }
.side-steps a[aria-current]::before { background: var(--fg); opacity: 1; }
.side-steps a:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; border-radius: 4px; }
.side-label {
  position: absolute;
  left: calc(100% + var(--frame) / 2 + 8px);
  top: 50%;
  transform: translateY(-50%);
  padding: 5px 10px;
  border-radius: 6px;
  background: var(--frame-bg);
  font-family: var(--font-display);
  font-size: var(--fs-s);
  font-weight: 600;
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--fg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.side-steps a:hover .side-label, .side-steps a:focus-visible .side-label { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .side-steps a::before, .side-label { transition: none; } }

/* Footer + legal */
.site-foot .wrap {
  padding-block: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  font-size: var(--fs-m);
  color: var(--muted);
}
.foot-link { text-decoration: none; padding-block: 6px; }
.foot-link:hover { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }
.foot-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 24px; }
.foot-links { display: flex; gap: 20px; }
.legal {
  border-top: 1px solid var(--line);
  padding-top: 16px;
}
.legal summary { cursor: pointer; font-weight: 600; color: var(--fg); padding-block: 6px; }
.legal p { margin: 8px 0 0; max-width: 65ch; }

@media (max-width: 860px) {
  .hero .wrap { grid-template-columns: minmax(0, 1fr); }
}
@media (min-width: 861px) {
  .hero .wrap { align-items: center; }
}

/* Phones: one rhythm for the whole page. Sections closer together (about 72 px of air between two blocks instead
   of 112), the steps stand in less from the left edge, and the
   contact buttons fill their rows instead of leaving one alone */
@media (max-width: 640px) {
  /* the headline block stands further from its content than the items of that content from each other */
  .section .wrap { padding-block: 36px; gap: 40px; }
  .statement { gap: 14px; }
  .steps { --gap: 24px; --icon: 20px; }
  .steps li { padding-left: calc(var(--icon) + 14px); }
  /* every section opens with its headline: here the portrait follows the headline, in the middle, before the text */
  .about { gap: 24px; }
  .about-text { display: contents; }
  .about-text > .statement { order: -1; }
  .about > .portrait { width: 220px; margin-block: -20px; }
  .about-band .wrap { padding-bottom: calc(36px + 46vw); } /* room for the Moon under the text */
  #contact .wrap { padding-bottom: calc(36px + 70vw); } /* and for the Sun under the buttons */
  .ws-list { gap: 28px; }
  /* the terminal opens no taller than its greeting needs; what follows scrolls inside, as before */
  .cli-screen { height: 220px; }
  .ws-list li { padding-top: 0; }
  .contact-row { gap: 12px; }
  .contact-row .btn { flex: 1 1 auto; justify-content: center; }
}

/* Slides: on wide, tall enough screens each section fills the frame and the page snaps from one to the next.
   The script keeps html.slides only while every section fits between the two tabs; otherwise the page scrolls
   as usual. The section in view is .is-active; the others wait faded and a little lower, so content never overlaps. */
html.slides { scroll-snap-type: y mandatory; }
/* with reduced motion the page only settles on a section that is already close; it never pulls */
@media (prefers-reduced-motion: reduce) { html.slides { scroll-snap-type: y proximity; } }
html.slides main > section {
  min-height: calc(100vh - 2 * var(--frame));
  min-height: calc(100dvh - 2 * var(--frame));
  scroll-snap-align: start;
  scroll-snap-stop: always;
  scroll-margin-top: var(--frame);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
html.slides main > section:is(.hero, .section) > .wrap { width: 100%; padding-block: calc(var(--tab-d) + 16px); }
html.slides .cli-screen { height: clamp(200px, calc(100dvh - 2 * var(--frame) - 2 * var(--tab-d) - 280px), 300px); }
html.slides main > section > .wrap { transition: opacity 0.45s ease, transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1); }
html.slides main > section:not(.is-active) > .wrap { opacity: 0; transform: translateY(28px); transition-duration: 0.25s; }
@media (prefers-reduced-motion: reduce) {
  html.slides main > section > .wrap, html.slides main > section:not(.is-active) > .wrap { opacity: 1; transform: none; transition: none; }
}
@media print { html.slides main > section > .wrap { opacity: 1 !important; transform: none !important; } }
