/* Reusable components: navigation, link lists, tags, project cards, media slot, bento tiles. */

/* ---------- Navigation, language switch, theme toggle ---------- */

.nav-list,
.lang-switch {
  display: flex;
  gap: var(--space-2xs) var(--space-md);
  white-space: nowrap;
}

.nav-list a,
.lang-switch a,
.lang-switch [aria-current] {
  display: inline-block;
  padding-block: var(--space-xs);
}

/* Two-letter codes: wide enough to be an easy target */
.lang-switch a,
.lang-switch [aria-current] {
  min-width: 1.75rem;
  text-align: center;
}

.lang-switch {
  gap: var(--space-2xs);
}

/* Section being read (set by topbar.js) */
.nav-list a[aria-current="true"] {
  color: var(--color-highlight);
  font-weight: 700;
  text-decoration-thickness: 0.16em;
}

.lang-switch {
  font-family: var(--font-mono);
}

.lang-switch [aria-current] {
  font-weight: 700;
  text-decoration: none;
}

.theme-toggle {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: var(--border-width) solid var(--color-accent);
  border-radius: 50%;
  background: var(--color-card);
  color: var(--color-accent);
  cursor: pointer;
}

/* Icons drawn by theme.js: a moon in the light theme (go dark), a sun in the dark theme (go light) */
.theme-toggle svg {
  width: 1.2rem;
  height: 1.2rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.theme-toggle__sun,
:root[data-theme="dark"] .theme-toggle__moon {
  display: none;
}

:root[data-theme="dark"] .theme-toggle__sun {
  display: block;
}

/* ---------- Contact / CV links ---------- */

.link-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-sm);
  margin-top: var(--space-lg);
}

.link-list a {
  display: inline-block;
  padding: var(--space-xs) var(--space-sm);
  border: var(--border-width) solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-card);
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: translate 0.15s ease-out;
}

.link-list a:hover {
  text-decoration: underline;
  translate: 0 -2px;
}

.link-list .link--primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 700;
}

.link-list--plain {
  margin-top: 0;
  gap: var(--space-2xs) var(--space-md);
}

.link-list--plain a {
  padding: var(--space-xs) 0;
  border: 0;
  background: none;
  text-decoration: underline;
}

.link-list--plain a:hover {
  translate: none;
}

/* ---------- Scroll hint: arrow shown at the top of the page, a click goes down to the orrery
   (needs scripting, like the orrery it points to) ---------- */

.scroll-hint {
  display: none;
}

@media (scripting: enabled) {
  .scroll-hint {
    position: fixed;
    bottom: var(--space-lg);
    left: 50%;
    z-index: 5;
    display: grid;
    place-items: center;
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 50%;
    background: var(--color-text);
    color: var(--color-bg);
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--color-bg) 70%, transparent);
    translate: -50% 0;
    transition:
      opacity 0.3s,
      visibility 0.3s,
      scale 0.15s ease-out;
  }

  .scroll-hint:hover {
    scale: 1.08;
  }

  .scroll-hint svg {
    width: 1.5rem;
    height: 1.5rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* Three bounces, then still: nothing keeps moving beyond five seconds (WCAG 2.2.2) */
    animation: scroll-hint-bob 1.5s 3;
  }

  .scroll-hint.is-hidden {
    opacity: 0;
    visibility: hidden;
  }
}

/* A few pixels up and down, starting and ending at rest so the last bounce stops where the arrow stays */
@keyframes scroll-hint-bob {
  from {
    translate: 0 0;
    animation-timing-function: ease-out;
  }

  25% {
    translate: 0 -0.2rem;
    animation-timing-function: ease-in-out;
  }

  75% {
    translate: 0 0.25rem;
    animation-timing-function: ease-in;
  }

  to {
    translate: 0 0;
  }
}

/* ---------- Tags: blue monospace text on a pale chip, as on the CV ---------- */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.tags li {
  padding: 0.05em 0.5em;
  border-radius: var(--radius-sm);
  background: var(--color-tag-bg);
  color: var(--color-tag-text);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

/* ---------- Dates and secondary text ---------- */

.date {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 700;
  line-height: var(--leading-tight);
  white-space: nowrap;
}

.meta {
  color: var(--color-muted);
}

/* ---------- Cards: shared look of project cards and bento tiles ----------
   A soft lift on hover, and a halo that follows the pointer (--mx / --my set by spotlight.js). */

.project,
.skills__group,
.entry,
.facts__group,
.tile {
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-card);
  box-shadow: var(--shadow-card);
  transition:
    transform 0.2s ease-out,
    box-shadow 0.2s ease-out,
    border-color 0.2s ease-out;
}

@media (hover: hover) {
  :is(.project, .skills__group, .entry, .facts__group, .tile):hover {
    border-color: var(--color-accent);
    /* Discreet halo under the pointer */
    background-image: radial-gradient(
      10rem circle at var(--mx, 50%) var(--my, 0%),
      color-mix(in srgb, var(--color-accent) 6%, transparent),
      transparent 70%
    );
    box-shadow: 0 0.6rem 1.6rem var(--color-shadow);
    transform: translateY(-3px);
  }
}

/* ---------- Project cards (laid out from the width of the list, not of the screen) ---------- */

.project-list {
  display: grid;
  gap: var(--space-lg);
  container-type: inline-size;
}

.project {
  display: grid;
  gap: var(--space-md);
  padding: var(--space-lg);
  scroll-margin-top: calc(var(--topbar-height) + var(--space-md));
}

/* Card selected in the orrery */
.project.is-selected {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px var(--color-accent);
}

.project__body {
  display: grid;
  gap: var(--space-sm);
  align-content: start;
  min-width: 0;
}

.project__header {
  display: grid;
  gap: var(--space-2xs) var(--space-xs);
}

.project__title {
  font-size: var(--text-md);
}

.project__org {
  color: var(--color-accent);
}

/* With enough room: title, dotted leader, then the date pinned to the right, as on the CV.
   The leader only shows when the title fits on one line. */
.project__header::before {
  grid-area: 1 / 2;
  align-self: end;
  height: 2px;
  margin-bottom: 0.3em;
  background: radial-gradient(circle closest-side, var(--color-border) 98%, transparent) 0 0 / 0.4em 2px repeat-x;
}

@container (min-width: 28rem) {
  .project__header {
    grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
    align-items: baseline;
  }

  .project__header::before {
    content: "";
  }

  .project__title {
    grid-area: 1 / 1;
  }

  .project__header .date {
    grid-area: 1 / 3;
  }

  .project__org {
    grid-area: 2 / 1 / auto / -1;
  }
}

/* Bullets: small plum triangles, as on the CV */
.project__points {
  display: grid;
  gap: var(--space-xs);
  padding-left: 1.1em;
}

.project__points li {
  position: relative;
}

.project__points li::before {
  content: "";
  position: absolute;
  top: 0.58em;
  left: -1.1em;
  width: 0.45em;
  height: 0.45em;
  background: var(--color-highlight);
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

.project__facts {
  display: grid;
  gap: var(--space-2xs) var(--space-md);
}

/* Labels: plum heading font, as on the CV */
.project__facts dt,
.skills dt,
.facts dt {
  font-family: var(--font-heading);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-highlight);
}

@media (min-width: 30em) {
  .project__facts {
    grid-template-columns: max-content 1fr;
    align-items: baseline;
  }
}

/* Wide list: media on the left, header and body stacked on the right */
@container (min-width: 42rem) {
  .project {
    grid-template-columns: var(--media-width) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "media header"
      "media body";
    gap: var(--space-sm) var(--space-lg);
  }

  .project__header {
    grid-area: header;
  }

  .project__media {
    grid-area: media;
  }

  .project__body {
    grid-area: body;
  }
}

/* ---------- Media slot: screenshot, clip or video; neutral visual when there is none ---------- */

.project__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  align-self: start;
  border-radius: var(--radius-md);
  /* Neutral visual shown when the slot holds no screenshot */
  background:
    radial-gradient(circle at 32% 55%, var(--color-border) 0 22%, transparent 22.5%),
    radial-gradient(circle at 62% 40%, var(--color-border) 0 9%, transparent 9.5%),
    var(--color-surface);
}

.project__media img,
.project__media video,
.project__media iframe {
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}

/* Play button added by video.js when data-video holds an id */
.video-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.video-play::before {
  content: "";
  grid-area: 1 / 1;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--color-accent);
}

.video-play::after {
  content: "";
  grid-area: 1 / 1;
  margin-left: 0.3rem;
  border-block: 0.7rem solid transparent;
  border-left: 1.15rem solid var(--color-accent-contrast);
}

.video-play:focus-visible {
  outline-offset: calc(-1 * var(--focus-width) - 2px);
  box-shadow: inset 0 0 0 calc(var(--focus-width) + 4px) var(--color-accent-contrast);
}

/* Pause / play button of a looping demo clip (data-clip), added by video.js */
.clip-toggle {
  position: absolute;
  right: var(--space-xs);
  bottom: var(--space-xs);
  min-height: 1.75rem;
  padding: 0.1rem 0.6rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: rgb(4 5 13 / 75%);
  color: #ffffff;
  font: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
}

/* ---------- Bento: skills, education and activities as tiles of different widths ---------- */

.skills,
.entries,
.facts {
  display: grid;
  gap: var(--space-md);
}

.skills__group,
.entry,
.facts__group,
.tile {
  display: grid;
  gap: var(--space-xs);
  align-content: start;
  padding: var(--space-md) var(--space-lg);
}

/* Date above the degree, like a small heading */
.entry .date {
  order: -1;
  color: var(--color-highlight);
}

/* Degree names use the heading font, as on the CV */
.entry__text strong {
  font-family: var(--font-heading);
  font-weight: 600;
}

@media (min-width: 40em) {
  .skills,
  .entries,
  .facts {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .skills__group,
  .entry,
  .facts__group {
    grid-column: span 3;
  }

  /* Education: the engineering degree takes the whole first row */
  .entry:first-child {
    grid-column: 1 / -1;
  }
}

@media (min-width: 64em) {
  /* Skills: 4 + 2, 2 + 4, then a full-width tile */
  .skills__group:nth-child(4n + 1),
  .skills__group:nth-child(4n + 4) {
    grid-column: span 4;
  }

  .skills__group:nth-child(4n + 2),
  .skills__group:nth-child(4n + 3) {
    grid-column: span 2;
  }

  .skills__group:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* Activities: 2 + 4, then 3 + 3 */
  .facts__group:nth-child(1) {
    grid-column: span 2;
  }

  .facts__group:nth-child(2) {
    grid-column: span 4;
  }
}

/* ---------- Link from a card to the project's own page ---------- */

.project__more {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  gap: 0.5em;
  padding: 0.3rem 0.8rem;
  border: var(--border-width) solid var(--color-accent);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 700;
  text-decoration: none;
}

.project__more:hover {
  text-decoration: underline;
}

/* Right chevron */
.project__more::after {
  content: "";
  width: 0.4em;
  height: 0.4em;
  border-top: 2px solid;
  border-right: 2px solid;
  rotate: 45deg;
}

/* ---------- Project page: hero, then a bento of visual, fact sheet, text, video ---------- */

.project-hero__kicker {
  margin-bottom: var(--space-xs);
  color: var(--color-accent);
}

/* Grey would be too faint on the hero's tinted background */
.project-hero__kicker .meta {
  color: inherit;
}

.project-hero .date {
  margin-top: var(--space-sm);
}

.project-hero .tags {
  margin-top: var(--space-md);
}

.project-page {
  display: grid;
  gap: var(--space-lg);
}

@media (min-width: 56em) {
  .project-page {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .project-page__visual {
    grid-column: span 4;
  }

  .project-page__sheet {
    grid-column: span 2;
  }

  .project-page__text,
  .project-nav {
    grid-column: 1 / -1;
  }

  .project-page__fact {
    grid-column: span 3;
  }
}

.media-frame {
  display: grid;
  gap: var(--space-xs);
  align-content: start;
}

.media-frame figcaption {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

/* Image slot: the picture of the project's card, or the neutral visual while there is none */
.project-page__image {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(circle at 32% 55%, var(--color-border) 0 22%, transparent 22.5%),
    radial-gradient(circle at 62% 40%, var(--color-border) 0 9%, transparent 9.5%),
    var(--color-surface);
  box-shadow: var(--shadow-card);
}

.project-page__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* With a video the top slot is the player, in the same frame as the picture it stands for */
.project-page__visual .project__media {
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}

.tile__title {
  color: var(--color-highlight);
  font-family: var(--font-heading);
  font-size: var(--text-md);
  font-weight: 600;
  line-height: var(--leading-tight);
}

.tile .project__points {
  margin-top: var(--space-xs);
}

.sheet {
  display: grid;
  gap: var(--space-sm);
}

.sheet dt {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

/* Previous / next project */
.project-nav {
  display: grid;
  gap: var(--space-md);
}

@media (min-width: 40em) {
  .project-nav {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .project-nav__next {
    grid-column: 2;
    text-align: right;
  }
}

.project-nav a {
  color: inherit;
  text-decoration: none;
}

.project-nav__label {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.project-nav__name {
  color: var(--color-accent);
  font-family: var(--font-heading);
  font-weight: 600;
}

/* ---------- Project page, case study: hand-written tiles (objectives, specification, results…) ---------- */

.case {
  grid-template-columns: minmax(0, 1fr); /* a wide table or figure must not stretch the tile, nor the page */
  gap: var(--space-sm);
  min-width: 0;
}

@media (min-width: 56em) {
  .case {
    grid-column: 1 / -1;
  }

  .case--half {
    grid-column: span 3;
  }
}

/* Numbered steps */
.steps {
  display: grid;
  gap: var(--space-xs);
  padding-left: 1.4em;
  list-style: decimal;
}

.steps li::marker {
  color: var(--color-highlight);
  font-weight: 700;
}

/* Specification: what was asked on the left, the answer on the right */
.spec {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.spec th,
.spec td {
  padding: var(--space-xs) var(--space-md) var(--space-xs) 0;
  border-top: var(--border-width) solid var(--color-card-border);
  overflow-wrap: anywhere; /* on a very narrow screen a long word breaks rather than widening the table */
  text-align: left;
  vertical-align: top;
}

.spec thead th {
  border-top: 0;
  color: var(--color-muted);
  font-size: var(--text-xs);
  font-weight: 400;
}

.spec tbody th {
  width: 30%;
  min-width: 7rem;
  hyphens: auto; /* in a narrow column a long word is cut at a syllable, with a hyphen */
}

.spec .spec__number {
  padding-right: 0;
  padding-left: var(--space-sm);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* Column headings of numbers read like the other headings, and may wrap on a narrow screen */
.spec thead .spec__number {
  font-family: inherit;
  white-space: normal;
}

/* A table of numbers gives its room to the numbers */
.spec:has(td.spec__number) tbody th {
  width: auto;
  min-width: 0;
}

/* Headline numbers */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10.5rem), 1fr));
  gap: var(--space-md);
}

.stat {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
  padding-left: var(--space-sm);
  border-left: 3px solid var(--color-card-border);
}

.stat__value {
  order: -1; /* the number first, its label under it */
  font-family: var(--font-heading);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: var(--leading-tight);
}

.stat--hero {
  border-left-color: var(--color-highlight);
}

.stat--hero .stat__value {
  color: var(--color-highlight);
  font-size: var(--text-2xl);
}

.stat__label {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

/* Screenshots and figures: centred in their frame, caption included */
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-md);
}

.shot {
  display: grid;
  gap: var(--space-xs);
  align-content: start;
  width: 100%;
  margin-inline: auto;
}

/* Side by side, the pictures share one row and the captions the next one:
   a shorter picture sits at mid-height of its neighbour, and the captions line up */
.shots > .shot {
  grid-row: span 2;
  grid-template-rows: subgrid;
}

.shot img {
  align-self: center;
  width: 100%;
  height: auto;
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-md);
  background-color: #ffffff; /* figures drawn on white stay on white in the dark theme */
}

.shot figcaption,
.chart__note {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.shot figcaption {
  text-align: center;
}

/* A figure too detailed for the size it is drawn at: a link in its caption opens the full picture,
   and the whole figure is the target of that link */
.shot--zoom {
  position: relative;
}

.shot__zoom {
  padding-block: 0.3rem; /* the words alone are a target 24px high, without moving the line */
  white-space: nowrap;
}

.shot__zoom::after {
  content: "";
  position: absolute;
  inset: 0;
  cursor: zoom-in;
}

/* A video inside a section: the frame is on the player, its poster fills it */
.shot .project__media {
  align-self: center;
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-md);
}

.shot .project__media img {
  height: 100%;
  border: 0;
  border-radius: 0;
}

.shot--narrow {
  max-width: 20rem;
}

.shot--medium {
  max-width: 42rem;
}

.shot--wide {
  max-width: 52rem;
}

/* A journey, stop after stop */
.route {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) 1.6rem;
}

.route li {
  position: relative;
  padding: 0.1rem 0.7rem;
  border: var(--border-width) solid var(--color-card-border);
  border-radius: 999px;
  background-color: var(--color-surface);
  font-size: var(--text-sm);
}

/* Chevron in the gap before each stop but the first */
.route li + li::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -1.05rem;
  width: 0.4rem;
  height: 0.4rem;
  border-top: 2px solid var(--color-muted);
  border-right: 2px solid var(--color-muted);
  translate: 0 -50%;
  rotate: 45deg;
}

.route .route__landing {
  border-color: var(--color-highlight);
}

.route__note {
  color: var(--color-highlight);
  font-size: var(--text-xs);
  font-weight: 700;
}

/* A few parts and what links them */
.pipeline {
  display: grid;
  gap: var(--space-lg);
}

.pipeline li,
.cards li {
  position: relative;
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
  padding: var(--space-sm) var(--space-md);
  border: var(--border-width) solid var(--color-card-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  font-size: var(--text-sm);
}

.pipeline strong,
.cards strong {
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: 600;
}

/* A set of small cards, one notion each: a name, its key (a question, a figure) and a line or two */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-sm);
}

.cards__key {
  color: var(--color-accent);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

/* Cards that open with a picture: fewer per row, so that the picture stays readable */
.cards--pictures {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}

.cards img {
  width: 100%;
  height: auto;
  margin-bottom: var(--space-2xs);
  border-radius: var(--radius-sm);
}

/* Link drawn in the gap between two parts: vertical when stacked, horizontal side by side */
.pipeline li + li::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-lg));
  left: 50%;
  width: 2px;
  height: var(--space-lg);
  background-color: var(--color-border);
}

@media (min-width: 48em) {
  .pipeline {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .pipeline li + li::before {
    top: 1.6rem; /* level with the names of the parts */
    left: calc(-1 * var(--space-lg));
    width: var(--space-lg);
    height: 2px;
  }
}

/* The picture that illustrates a part */
.pipeline .shot {
  margin-top: var(--space-xs);
}

/* On the tinted surface the muted grey is too faint for small text (4.3:1): captions take the text colour */
.pipeline figcaption,
.cards figcaption {
  color: var(--color-text);
}

/* ---------- Chart: from a baseline to a result on one axis (dumbbell).
   Each row sets --from and --to, in % of the axis. Values are written beside the dots,
   and the same numbers are in the table under the chart. ---------- */

.chart {
  display: grid;
  gap: var(--space-sm);
}

.chart__title {
  font-size: var(--text-sm);
  font-weight: 700;
}

.chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.chart__key {
  display: inline-block;
  width: 0.625rem;
  height: 0.625rem;
  margin-right: 0.4em;
  border-radius: 50%;
  background-color: var(--chart-rest);
}

.chart__key--focus {
  background-color: var(--chart-focus);
}

/* One series as horizontal bars: each row sets --v, its value as a fraction of the largest one.
   The value is written at the tip of its bar; the same numbers are in the tables under the chart. */
.bars {
  display: grid;
  gap: var(--space-xs);
  max-width: 46rem;
}

.bars__row {
  display: grid;
  gap: var(--space-2xs);
}

@media (min-width: 40em) {
  .bars__row {
    grid-template-columns: 11rem minmax(0, 1fr);
    gap: var(--space-sm);
    align-items: center;
  }
}

.bars__name {
  font-size: var(--text-sm);
}

.bars__track {
  display: flex;
  gap: var(--space-xs);
  align-items: center;
  border-left: 1px solid var(--chart-grid); /* the baseline every bar grows from */
}

.bars__bar {
  flex: 0 0 calc((100% - 3.5rem) * var(--v));
  height: 0.875rem;
  border-radius: 0 4px 4px 0;
  background-color: var(--chart-focus);
}

.bars__value {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.dumbbell {
  --label-room: 4.5rem; /* on each side of the axis, for the values */
  display: grid;
  gap: var(--space-xs);
  max-width: 46rem;
}

.dumbbell__row {
  display: grid;
  gap: var(--space-2xs);
}

@media (min-width: 40em) {
  .dumbbell__row {
    grid-template-columns: 7.5rem minmax(0, 1fr);
    gap: var(--space-sm);
    align-items: center;
  }
}

.dumbbell__name {
  font-size: var(--text-sm);
}

/* Hairlines every 50 000, from 0 to 200 000, on an axis running from -25 000 to 225 000 */
.dumbbell__track,
.dumbbell__axis {
  position: relative;
  margin-inline: var(--label-room);
}

.dumbbell__track {
  height: 2rem;
  background:
    linear-gradient(var(--chart-grid) 0 0) 10% 0 / 1px 100% no-repeat,
    linear-gradient(var(--chart-grid) 0 0) 30% 0 / 1px 100% no-repeat,
    linear-gradient(var(--chart-grid) 0 0) 50% 0 / 1px 100% no-repeat,
    linear-gradient(var(--chart-grid) 0 0) 70% 0 / 1px 100% no-repeat,
    linear-gradient(var(--chart-grid) 0 0) 90% 0 / 1px 100% no-repeat;
}

.dumbbell__link {
  position: absolute;
  top: 50%;
  left: var(--from);
  width: calc(var(--to) - var(--from));
  height: 2px;
  background-color: var(--color-border);
  translate: 0 -50%;
}

.dumbbell__dot {
  position: absolute;
  top: 50%;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--color-card); /* ring in the surface colour: two close dots stay distinct */
  translate: -50% -50%;
}

.dumbbell__dot--rest {
  left: var(--from);
  background-color: var(--chart-rest);
}

.dumbbell__dot--focus {
  left: var(--to);
  background-color: var(--chart-focus);
}

.dumbbell__value {
  position: absolute;
  top: 50%;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  translate: 0 -50%;
}

.dumbbell__value--rest {
  right: calc(100% - var(--from) + 0.7rem);
}

.dumbbell__value--focus {
  left: calc(var(--to) + 0.7rem);
}

.dumbbell__axis {
  height: 1.25rem;
  color: var(--color-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

@media (min-width: 40em) {
  .dumbbell__axis {
    margin-left: calc(7.5rem + var(--space-sm) + var(--label-room));
  }
}

.dumbbell__axis span {
  position: absolute;
  top: 0;
  left: var(--at);
  white-space: nowrap;
  translate: -50% 0;
}

/* ---------- Reveal on scroll: blocks below the fold come up once, then stay (class set by reveal.js).
   Declared after the cards so their hover transitions are kept alongside the reveal. ---------- */

.reveal {
  opacity: 0;
  translate: 0 2rem;
  transition:
    opacity 0.4s ease-out,
    translate 0.5s cubic-bezier(0.2, 0.7, 0.2, 1),
    transform 0.2s ease-out,
    box-shadow 0.2s ease-out,
    border-color 0.2s ease-out;
}

.reveal.is-visible {
  opacity: 1;
  translate: none;
}

/* ---------- Reduced motion, print ---------- */

@media (prefers-reduced-motion: reduce) {
  .scroll-hint,
  .link-list a,
  .project,
  .skills__group,
  .entry,
  .facts__group,
  .tile {
    transition: none;
  }

  .scroll-hint svg {
    animation: none;
  }

  :is(.project, .skills__group, .entry, .facts__group, .tile):hover {
    transform: none;
  }
}

/* Never leave a block hidden on paper or when motion is unwanted */
@media print, (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    translate: none;
    transition: none;
  }
}

/* ---------- Paper: the content only, on white ---------- */

@media print {
  .topbar,
  .scroll-hint,
  .skip-link,
  .orrery,
  .video-play,
  .shot__zoom,
  .project-nav {
    display: none !important;
  }

  body {
    border: 0;
    background: #ffffff;
  }

  body::before {
    display: none;
  }

  .section,
  .site-header {
    padding-block: var(--space-md);
  }

  .project,
  .tile,
  .skills__group,
  .entry,
  .facts__group,
  figure,
  tr {
    break-inside: avoid;
    box-shadow: none;
  }

  h2,
  h3 {
    break-after: avoid;
  }

  /* A link's address is its only use on paper */
  .site-footer a[href^="http"]::after,
  .link-list a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-weight: 400;
    overflow-wrap: anywhere;
  }
}

/* ---------- Windows high contrast (forced colours): marks drawn with a background colour would vanish;
   they are redrawn in the system's text colour. The data of every chart is also in the table under it. ---------- */

@media (forced-colors: active) {
  .bars__bar,
  .dumbbell__dot,
  .dumbbell__link,
  .chart__key {
    forced-color-adjust: none;
    background-color: CanvasText;
  }

  .dumbbell__dot--focus,
  .chart__key--focus {
    background-color: Highlight;
  }

  .video-play::before {
    forced-color-adjust: none;
    background: ButtonFace;
    border: 2px solid ButtonText;
  }

  .video-play::after {
    forced-color-adjust: none;
    border-left-color: ButtonText;
  }

  /* A tag is only told apart by its background */
  .tags li {
    border: 1px solid CanvasText;
  }
}
