/* templ.ch, Design "Signal". Ein dunkles Thema, Tokens aus der Spezifikation 4.1. */
:root {
  --ground: #0b0f0e;
  --surface: #121816;
  --line: #243029;
  --text: #e9efeb;
  --muted: #97a39c;
  --v0: #440154; --v1: #414487; --v2: #2a788e; --v3: #22a884; --v4: #7ad151; --v5: #fde725;
  --link: #7ad151;
  --accent: #fde725;
  --gutter: 24px;
  --max: 1240px;
  --font-text: "Bricolage Grotesque", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html { background: var(--ground); }
body {
  margin: 0; background: var(--ground); color: var(--text);
  font-family: var(--font-text); font-variation-settings: "opsz" 14, "wdth" 100;
  font-size: 17px; line-height: 1.55; padding-inline: var(--gutter);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Links in Fliesstext duerfen sich nicht allein auf Farbe verlassen (Lighthouse a11y). */
main p a, main li a, main dd a, main td a, .site-footer a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; text-decoration-color: color-mix(in srgb, currentColor 60%, transparent); }
main p a:hover, main li a:hover, main dd a:hover, main td a:hover, .site-footer a:hover { text-decoration-color: currentColor; }
main p.more a { text-decoration: none; }
/* Die Filter der Publikationsliste sind Schaltflaechen (role=button), keine Fliesstext-Links. */
main p.filters a { text-decoration: none; }
h1, h2, h3, h4, p, figure { margin: 0; }
h1 { font-variation-settings: "opsz" 96, "wdth" 78; font-weight: 760; font-size: clamp(2.8rem, 7.2vw, 6.4rem); line-height: 0.96; letter-spacing: -0.03em; text-wrap: balance; }
h2 { font-variation-settings: "opsz" 48, "wdth" 92; font-weight: 640; font-size: clamp(1.7rem, 3vw, 2.5rem); line-height: 1.08; letter-spacing: -0.015em; text-wrap: balance; }
h3 { font-weight: 620; font-size: 1.08rem; line-height: 1.3; }
p { max-width: 70ch; text-wrap: pretty; }
.mono, .label, .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.label { font-size: 0.8rem; color: var(--muted); letter-spacing: 0.02em; }
.wrap { max-width: var(--max); margin-inline: auto; }
/* Nachgestellter Verweis unter einem Block, etwa "alle Projekte" oder die Linkzeile der Software. */
.more { margin-top: 1rem; }
.skip { position: absolute; left: -999px; top: 8px; background: var(--accent); color: #111; padding: 6px 10px; z-index: 10; }
.skip:focus { left: 12px; }

/* Kopf und Navigation */
.site-header { max-width: var(--max); margin-inline: auto; }
.site-header nav { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding-block: 16px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.site-header .name { font-weight: 700; font-variation-settings: "opsz" 24, "wdth" 90; font-size: 1.05rem; color: var(--text); }
.site-header ul { list-style: none; margin: 0; padding: 0; display: flex; gap: 1.2rem; flex-wrap: wrap; font-family: var(--font-mono); font-size: 0.85rem; }
.site-header ul a { color: var(--text); }
.site-header ul a[aria-current="page"] { color: var(--v4); }
.site-header .lang a { border: 1px solid var(--line); padding: 1px 7px; }

/* Abschnitte */
main { max-width: var(--max); margin-inline: auto; overflow-wrap: anywhere; }
section { padding-block: 48px 56px; border-bottom: 1px solid var(--line); }
.head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.6rem; }
.page-title { padding-block: 40px 8px; }
.page-title h1 { font-size: clamp(2.2rem, 5vw, 4rem); }
.page-title p { color: var(--muted); margin-top: 0.8rem; font-size: 1.05rem; }
.cols-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
.cols-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem var(--gutter); }
.cols-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gutter); }

/* Listen mit Jahr oder Datum links */
ol.dated, ul.plain { list-style: none; margin: 0; padding: 0; }
ol.dated li { display: grid; grid-template-columns: 6.5rem minmax(0, 1fr); gap: 1rem; padding-block: 9px; border-top: 1px solid var(--line); font-size: 0.98rem; }
ol.dated .d { font-family: var(--font-mono); font-size: 0.85rem; color: var(--v4); padding-top: 3px; }
ol.dated .v, ul.plain small { color: var(--muted); }
ul.plain li { padding-block: 9px; border-top: 1px solid var(--line); font-size: 0.98rem; }
ul.plain li small { display: block; font-size: 0.88rem; }

/* Tabellen */
.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.95rem; }
th, td { text-align: left; vertical-align: top; padding: 8px 14px 8px 0; border-bottom: 1px solid var(--line); }
th { font-family: var(--font-mono); font-weight: 500; font-size: 0.8rem; color: var(--muted); }
td.n, th.n { text-align: right; padding-right: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Fuss */
.site-footer { max-width: var(--max); margin-inline: auto; padding-block: 24px 44px; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; color: var(--muted); font-size: 0.9rem; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; gap: 1.2rem; flex-wrap: wrap; }

@media (max-width: 900px) {
  .cols-3, .cols-2 { grid-template-columns: minmax(0, 1fr); }
  .cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  :root { --gutter: 16px; }
  body { padding-inline: var(--gutter); }
  .site-header ul { gap: 0.9rem; }
  ol.dated li { grid-template-columns: 5.4rem minmax(0, 1fr); }
  .cols-4 { grid-template-columns: minmax(0, 1fr); }
  /* Die SVG-Grafiken skalieren auf Telefonbreite herunter, ihre 11px-Beschriftung wird dabei
     unlesbar klein. Diese Regel schlaegt das "text{}" im <style> der Grafik selbst, weil sie
     spezifischer ist (Klasse plus zwei Elemente gegen ein Element). */
  .charts svg text { font-size: 15px; }
  /* Die Legende ist die Ausnahme: ihre x-Positionen rechnet works_svg() fest aus (char_w = 6.5,
     auf 11 Einheiten bemessen). Bei 15 deckte in Chrome das naechste Quadrat das Ende des vorigen
     Wortes zu -- im Deutschen an fuenf Stellen -- und "andere" ragte aus der viewBox. 12 ist der
     groesste Wert, bei dem alle sechs Beschriftungen beider Sprachen noch frei stehen. */
  .charts svg text.legend-label { font-size: 12px; }
  /* Auf Telefonbreite steht die Infografik sonst in der zweiten Rasterspalte neben der Datumsspalte,
     nur rund 207px breit -- die 12px-SVG-Beschriftung waere dort unlesbar klein. Sie spannt deshalb
     die ganze Zeile, behaelt ihre Textgroesse und scrollt im Rahmen kurz waagrecht statt zu schrumpfen.
     Das Rasterspalten-Grid-column selbst steht unten bei der Projekte-Sektion (nach der 1100px-Regel
     fuer Tablets), weil beide Regeln dieselbe Selektor-Spezifitaet haben und sich bei Telefonbreite
     ueberlagern -- gewinnt sonst die spaeter im Stylesheet stehende 1100px-Regel. */
  .projects-list li.with-fig .infographic svg { min-width: 420px; }
  dialog.fig-dialog { overflow-x: auto; }
  dialog.fig-dialog svg { min-width: 420px; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  /* Spezifikation 4.5: das Video-Band steht still, auch ohne JavaScript. Der Pfad ist relativ
     zu assets/site.css, das Standbild liegt also unter /assets/media/loop-poster.jpg. */
  .now video { display: none; }
  .now { background: url(media/loop-poster.jpg) center / cover no-repeat; }
}

/* Projekte */
.projects > article { background: rgba(18,24,22,0.82); border: 1px solid var(--line); padding: 18px 18px 20px; display: flex; flex-direction: column; gap: 8px; }
.projects .when { font-family: var(--font-mono); font-size: 0.8rem; color: var(--v4); }
.projects p { color: var(--muted); font-size: 0.95rem; }
.projects-list li { grid-template-columns: 7.5rem minmax(0, 1fr); padding-block: 16px; }
.projects-list h3 { margin-bottom: 4px; }
.projects-list .v { font-family: var(--font-mono); font-size: 0.8rem; margin-bottom: 6px; }
.projects-list .links { margin-top: 6px; font-size: 0.85rem; }
.projects-list li.with-fig { grid-template-columns: 7.5rem minmax(0, 1fr) minmax(0, 400px); }
.infographic { margin: 0; align-self: start; }
.infographic svg { width: 100%; height: auto; display: block; }
.infographic figcaption { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); margin-top: 6px; }
.infographic.can-open { cursor: zoom-in; }
.infographic.can-open:hover figcaption, .infographic.can-open:focus-visible figcaption { color: var(--text); }
dialog.fig-dialog { background: var(--ground); color: var(--text); border: 1px solid var(--line); padding: 20px 24px 24px; width: min(96vw, 1100px); max-width: none; }
dialog.fig-dialog::backdrop { background: rgba(11,15,14,0.92); }
dialog.fig-dialog svg { width: 100%; height: auto; display: block; margin-top: 12px; }
dialog.fig-dialog figcaption { font-family: var(--font-mono); font-size: 0.85rem; color: var(--muted); margin-top: 8px; }
.fig-close { float: right; background: none; color: var(--text); border: 1px solid var(--line); padding: 6px 12px; font-size: 0.85rem; cursor: pointer; }
.fig-close:hover { border-color: var(--v4); }
@media (max-width: 1100px) { .projects-list li.with-fig { grid-template-columns: 7.5rem minmax(0, 1fr); } .projects-list li.with-fig .infographic { grid-column: 2; } }
/* Muss nach der 1100px-Regel stehen: gleiche Selektor-Spezifitaet, bei <=720px greifen beide
   Media-Queries gleichzeitig, und ohne wichtigere Spezifitaet gewinnt die spaetere Regel im
   Stylesheet -- hier also absichtlich diese, damit die Infografik auf Telefonbreite die ganze
   Zeile spannt statt in der 207px schmalen Tablet-Spalte zu stehen (siehe 720px-Block oben). */
@media (max-width: 720px) { .projects-list li.with-fig .infographic { grid-column: 1 / -1; overflow-x: auto; } }

/* Konsole */
.console { background: var(--surface); border: 1px solid var(--line); padding: 18px 20px; font-family: var(--font-mono); font-size: 0.9rem; line-height: 1.65; }
.console .p { color: var(--v4); }
.console .c { color: var(--muted); }
.console table { min-width: 620px; }
.console td { padding: 3px 18px 3px 0; border: 0; vertical-align: top; }
.console td.pkg { color: var(--text); font-weight: 500; }
.console td.d { color: var(--muted); font-family: var(--font-text); font-size: 0.95rem; }
.console th { text-align: left; font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); font-weight: 400; padding: 0 0 6px; }
.console th:last-child { text-align: right; }

/* Publikationen */
.metrics .n { font-family: var(--font-mono); font-size: clamp(2rem, 4vw, 3rem); font-weight: 500; line-height: 1; }
.metrics .d { color: var(--muted); font-size: 0.9rem; margin-top: 8px; }
.charts { margin-top: 24px; }
.charts svg { width: 100%; height: auto; display: block; }
.charts figure { margin: 0; }
.charts figcaption { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); margin-top: 6px; }
.chart-switch .filters { margin-bottom: 8px; }
.chart-switch figure[hidden] { display: none; }
.chart-switch figure + figure { margin-top: 24px; }
.books .book { border-top: 2px solid var(--v2); padding-top: 12px; display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 14px; align-items: start; }
.books .book.no-cover { display: block; }
.books .cover img { display: block; width: 88px; height: auto; border: 1px solid var(--line); }
.books .d { font-family: var(--font-mono); font-size: 0.8rem; color: var(--v4); }
.books p { color: var(--muted); font-size: 0.92rem; margin-top: 6px; }
.filters a { margin-right: 0.6rem; }
.filters a[aria-pressed="true"] { color: var(--accent); }
ol.pubs li[hidden] { display: none; }

/* Forschung */
.themes .theme { padding-block: 28px; border-top: 1px solid var(--line); display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 1rem var(--gutter); }
.themes .theme h3 { grid-column: 1; font-size: 1.3rem; font-variation-settings: "opsz" 32, "wdth" 92; }
.themes .theme > p { grid-column: 1; }
.themes .theme ol { grid-column: 2; grid-row: 1 / span 3; }
@media (max-width: 900px) { .themes .theme { grid-template-columns: minmax(0, 1fr); } .themes .theme ol { grid-column: 1; grid-row: auto; } }

/* Lehre und Vorträge */
.note { margin-top: 1.2rem; border-left: 3px solid var(--v3); padding-left: 14px; }
.talks .kind { font-size: 0.75rem; color: var(--v5); margin-left: 6px; }
.talks-chart svg { width: 100%; max-width: 760px; height: auto; display: block; }
.talks-chart figure { margin: 0; }
.talks-chart figcaption { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); margin-top: 6px; }
@media (max-width: 720px) { .talks-chart svg text { font-size: 15px; } .talks-chart svg text.legend-label { font-size: 12px; } }

/* FAIR Press */
.fp .quote { font-variation-settings: "opsz" 72, "wdth" 82; font-weight: 700; font-size: clamp(2rem, 4.6vw, 4rem); line-height: 1.02; letter-spacing: -0.025em; max-width: 20ch; text-wrap: balance; }
.fp .rule { height: 6px; background: linear-gradient(90deg, var(--v0), var(--v1), var(--v2), var(--v3), var(--v4), var(--v5)); margin: 1.6rem 0 1.8rem; max-width: 520px; }
.fp .cols-3 p, .fp p { color: var(--muted); font-size: 0.98rem; margin-top: 4px; }
.fp .status { display: inline-block; margin-top: 8px; font-size: 0.78rem; color: var(--v5); }
.cta { margin-top: 1.8rem; display: flex; gap: 1.6rem; flex-wrap: wrap; font-size: 0.9rem; }
ol.model { padding-left: 1.2rem; max-width: 70ch; }
ol.model li { margin-bottom: 0.5rem; }

/* CV */
.cv-top { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: var(--gutter); align-items: start; }
.cv-top .bio + .bio { margin-top: 1.4rem; }
.portrait img { display: block; width: 100%; max-width: 420px; height: auto; border: 1px solid var(--line); }
.portrait figcaption { margin-top: 6px; }
.bio h3 { margin-bottom: 6px; }
@media (max-width: 900px) { .cv-top { grid-template-columns: minmax(0, 1fr); } }

/* Startseite: Hero (Text), Hüte */
.hero { position: relative; margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); min-height: 560px; padding-block: 56px 40px; display: grid; align-items: end; overflow: hidden; border-bottom: 1px solid var(--line); }
.hero .fore { position: relative; max-width: var(--max); margin-inline: auto; width: 100%; display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: var(--gutter); row-gap: 2rem; align-items: end; }
.hero h1 { max-width: 12ch; text-shadow: 0 2px 30px rgba(11,15,14,0.9); }
.hero .intro { margin-top: 1.2rem; max-width: 46ch; font-size: 1.08rem; text-shadow: 0 1px 18px rgba(11,15,14,0.95); }

/* Hero-Demo. Die Poster haengen an ".hero:not(.live)": hero.js ergaenzt "live" erst, wenn die
   Binaerdatei da ist und der Canvas zeichnet. Ohne JavaScript oder bei einem Ladefehler bleiben
   die Poster stehen, die Schaltflaechen bleiben gesperrt, die Kennzahlen zeigen das Original. */
.hero:not(.live) { background: url(hero-poster.png) right top / cover no-repeat; }
.hero:not(.live) .olten canvas { background: url(hero-olten.png) center / cover no-repeat; }
/* Am Telefon zeigt cover nur einen Ausschnitt des Posters; so liegt die Karte des Posters dort, wo
   layout() in hero.js sie zeichnet (zentriert, oben). */
@media (max-width: 900px) { .hero:not(.live) { background-size: 146% auto; background-position: 97% 6vw; } }
.hero canvas#hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.demo { background: rgba(18,24,22,0.78); border: 1px solid var(--line); padding: 14px 16px 14px; backdrop-filter: blur(5px); }
.demo .states { display: flex; border: 1px solid var(--line); padding: 0; margin: 0 0 12px; position: relative; }
.demo .states legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.demo .states label { flex: 1; text-align: center; font-family: var(--font-mono); font-size: 0.8rem; padding: 7px 4px; cursor: pointer; color: var(--muted); position: relative; }
.demo .states label + label { border-left: 1px solid var(--line); }
.demo .states input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.demo .states input:checked + span { color: var(--accent); }
.demo .states input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 3px; }
.demo .states input:disabled + span { opacity: 0.6; }
.demo .states label:has(input:disabled) { cursor: default; }
.demo .close { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 12px; align-items: start; }
.demo .olten { margin: 0; }
.demo .olten canvas { display: block; width: 100%; aspect-ratio: 2 / 1; border: 1px solid var(--line); background: #0b0f0e; }
.demo .olten figcaption { margin-top: 4px; font-family: var(--font-mono); font-size: 0.72rem; color: var(--muted); }
.demo .stats-title { font-family: var(--font-mono); font-size: 0.8rem; color: var(--muted); margin: 0 0 4px; }
.demo dl { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 1rem; margin: 0; font-family: var(--font-mono); font-size: 0.85rem; }
.demo dt { color: var(--muted); }
.demo dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; color: var(--accent); }
.demo .sentence { margin-top: 10px; font-size: 0.85rem; color: var(--muted); line-height: 1.4; }
.demo .source { margin-top: 6px; font-size: 0.72rem; color: var(--muted); }
/* Unter 900 px steht die Karte oben ueber dem Text (layout() in hero.js setzt sie dann zentriert
   an den oberen Rand), das Fenster Olten unter den Schaltflaechen. */
@media (max-width: 900px) { .hero .fore { grid-template-columns: minmax(0, 1fr); padding-top: 66vw; } .demo .close { grid-template-columns: minmax(0, 1fr); } }

.hats > div { border-top: 2px solid; padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.hats > div:nth-child(1) { border-color: var(--v2); }
.hats > div:nth-child(2) { border-color: var(--v3); }
.hats > div:nth-child(3) { border-color: var(--v4); }
.hats > div:nth-child(4) { border-color: var(--v5); }
.hats p { color: var(--muted); font-size: 0.98rem; }
.hats a { margin-top: auto; font-size: 0.85rem; }

/* Now mit Video-Band */
.now { position: relative; margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); overflow: hidden; }
.now video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0.75; }
.now::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(11,15,14,0.88) 0%, rgba(11,15,14,0.6) 55%, rgba(11,15,14,0.25) 100%); }
.now .inner { position: relative; z-index: 1; max-width: var(--max); margin-inline: auto; }
.now .more { margin-top: 1rem; }
