/* ==========================================================================
   Faro Schäfer — homepage
   Restrained charcoal-and-brass design, dark by default with a light variant.
   ========================================================================== */

/* Dark is the default and the no-JS fallback. The inline script in base.html
   sets `data-theme` on <html> before first paint (saved choice, else the OS
   preference); the header toggle flips it. Every colour on the site goes
   through these tokens, so a new component only needs to use them to work in
   both themes. */
:root {
  /* Manrope for text, Space Grotesk for headings and display text.
     The token keeps its name --font-serif although the face is a grotesque. */
  --font-sans: "Manrope", system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --font-serif: "Space Grotesk", system-ui, -apple-system, Segoe UI, sans-serif;

  --bg: #111315;
  --bg-alt: #181b1e;
  --surface: #1a1d21;
  --text: #e8e6e1;
  --muted: #9a9892;
  --border: #2a2d31;
  --accent: #c2ab84;
  --accent-contrast: #111315;
  --shadow: 0 1px 2px rgba(0, 0, 0, .25), 0 8px 24px rgba(0, 0, 0, .25);
  --shadow-hover: 0 2px 6px rgba(0, 0, 0, .35), 0 16px 40px rgba(0, 0, 0, .4);

  /* Overlays on photos and media (Home preview and phone cards, lightbox
     backdrop, game messages) stay light on a dark shade in both themes, so
     these are not redefined for light mode. */
  --media-shade: #111315;
  --media-text: #f1efea;
  --media-accent: #c2ab84;

  --maxw: 1000px;
  --radius: 4px;

  /* Tour map (tours.js reads --cat-* and --map-*, so the theme switch
     restyles the map too). */
  --faint: #6b6a66;
  --glass: rgba(17, 19, 21, .88);
  --cat-alpine-mountaineering: #b493ff;
  --cat-mountaineering: #5fcf8c;
  --cat-long-distance-hike: #ff7a66;
  --cat-ski-tour: #64aefc;
  --cat-trail-run: #3fd3c6;
  --cat-cycling: #f5b23d;
  --map-land: #1a1c1f;
  --map-water: #101316;
  --map-ice: #23272b;
  --map-shadow: #000000;
  --map-highlight: #4a4e54;
  --map-contour: rgba(255, 255, 255, .07);
  --map-contour-major: rgba(255, 255, 255, .13);
  --map-road: #2e3236;
  --map-path: #3a3e43;
  --map-boundary: #4d5157;
  --map-label: #8f8d88;
  --map-label-strong: #b7b4ae;
  --map-halo: #1a1c1f;
  --map-sky: #23272b;

  color-scheme: dark;
}
:root[data-theme="light"] {
  --bg: #f8f6f1;
  --bg-alt: #efece5;
  --surface: #ffffff;
  --text: #1c1b19;
  --muted: #5f5b54;
  --border: #dcd6cb;
  --accent: #7d6233;
  --accent-contrast: #ffffff;
  --shadow: 0 1px 2px rgba(40, 32, 16, .06), 0 6px 18px rgba(40, 32, 16, .06);
  --shadow-hover: 0 2px 6px rgba(40, 32, 16, .1), 0 14px 34px rgba(40, 32, 16, .12);

  --faint: #8f8a81;
  --glass: rgba(255, 255, 255, .92);
  --cat-alpine-mountaineering: #6b3fc4;
  --cat-mountaineering: #198049;
  --cat-long-distance-hike: #d23a26;
  --cat-ski-tour: #1d6dd0;
  --cat-trail-run: #008f88;
  --cat-cycling: #d27400;
  --map-land: #ecebe8;
  --map-water: #d3d7da;
  --map-ice: #f7f7f6;
  --map-shadow: #5c5c5c;
  --map-highlight: #ffffff;
  --map-contour: rgba(0, 0, 0, .07);
  --map-contour-major: rgba(0, 0, 0, .14);
  --map-road: #ffffff;
  --map-path: #c9c6c0;
  --map-boundary: #a9a59e;
  --map-label: #75716a;
  --map-label-strong: #45423d;
  --map-halo: #ecebe8;
  --map-sky: #dfe3e6;

  color-scheme: light;
}

* { box-sizing: border-box; }

/* Anchor jumps and keyboard focus stop below the sticky header. */
html { scroll-behavior: smooth; scroll-padding-top: 84px; }

body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: 32px;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

h1, h2, h3 { font-family: var(--font-serif); font-weight: 500; line-height: 1.2; letter-spacing: -0.005em; }
h3 { letter-spacing: 0; }   /* small display sizes crowd with any negative tracking */

img { max-width: 100%; height: auto; display: block; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--accent-contrast);
  padding: 8px 14px;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--border);
}
/* Everything in the bar shares one text baseline (the small uppercase language
   switch would sit high if centred as a box); the icon button is centred. */
.nav {
  display: flex;
  align-items: baseline;
  gap: 28px;
  height: 68px;
  padding-top: 19px;
}
.brand {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  color: var(--text);
}
.brand:hover { text-decoration: none; color: var(--accent); }
.nav-links { display: flex; align-items: baseline; gap: 28px; margin-left: auto; }
.nav-links > a {
  color: var(--muted);
  font-size: .88rem;
  letter-spacing: .01em;
}
.nav-links > a:hover { color: var(--text); text-decoration: none; }
.nav-links > a.active { color: var(--text); }
/* Inline links, so the block pseudo-element sits below the label. */
.nav-links > a.active::after {
  content: "";
  display: block;
  height: 1px;
  background: var(--accent);
  margin-top: 2px;
}
.lang-switch {
  color: var(--muted);
  font-size: .75rem;
  letter-spacing: .1em;
}
.lang-switch:hover { color: var(--text); text-decoration: none; }
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-left: -7px;   /* cancels the 7px around the 16px icon, so the gap to the icon matches the nav gap */
  align-self: flex-start;  /* from the bar's padding edge; the 3px puts the icon on the text's middle (tuned for Manrope) */
  margin-top: 3px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.theme-toggle[hidden] { display: none; }
.theme-toggle:hover { color: var(--text); border-color: var(--border); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle svg { width: 16px; height: 16px; }
/* Show what a click switches *to*. */
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* ---------- contact call to action (Consulting) ---------- */
.contact-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px 32px;
  margin-top: 32px;
  padding: 22px 26px;
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
}
.contact-cta-text { flex: 1 1 320px; }
.contact-cta-prompt { margin: 0 0 4px; font-family: var(--font-serif); font-size: 1.3rem; color: var(--text); }
.contact-cta-note { margin: 0; color: var(--muted); font-size: .95rem; max-width: 52ch; }
.btn {
  display: inline-flex;
  align-items: center;
  padding: 10px 22px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-contrast);
  font-weight: 500;
  font-size: .95rem;
  border: 0;
  font-family: inherit;
  cursor: pointer;
}
.btn:hover { filter: brightness(1.08); }

/* ---------- toast (copied email address) ---------- */
.toast {
  position: fixed;
  left: 24px;
  bottom: 24px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100vw - 48px);
  padding: 14px 20px 14px 16px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 1rem;
  font-weight: 500;
  box-shadow: var(--shadow-hover);
  opacity: 0;
  transform: translateY(12px) scale(.98);
  transition: opacity .25s ease, transform .25s ease;
}
/* A check mark in a ring (an exclamation mark when copying failed), drawn in
   CSS so the text stays the only content. */
.toast::before {
  content: "\2713";
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  font-size: .8rem;
}
.toast.is-failed::before { content: "!"; font-weight: 600; }
.toast.is-visible { opacity: 1; transform: none; }
.toast[hidden] { display: none; }

/* ---------- layout rhythm ---------- */
main.container { padding-top: 64px; padding-bottom: 96px; }
.page-head { margin-bottom: 48px; }
.page-title { font-size: clamp(2.2rem, 4.5vw, 3rem); font-weight: 400; margin: 0 0 .3em; }
.lead { color: var(--muted); font-size: 1.1rem; max-width: 62ch; margin: 0; }
/* Page intros are justified like the Home bio (left-aligned on phones). */
.page-head .lead { text-align: justify; hyphens: auto; }

/* ---------- hero (home) ---------- */
/* Eyebrow, name and a three-paragraph bio; the portrait floats right inside
   the bio, so the text runs beside it and then underneath. The list of pages
   follows below a rule. */
main.container:has(> .hero) { padding-top: 0; }
.hero {
  padding: 88px 0 64px;
  border-bottom: 1px solid var(--border);
}
.hero-text::after { content: ""; display: block; clear: both; }
.hero-eyebrow {
  text-transform: uppercase;
  letter-spacing: .16em;
  font-size: .78rem;
  font-weight: 500;
  color: var(--accent);
  margin: 0 0 16px;
}
.hero-text h1 {
  font-weight: 400;
  font-size: clamp(2.8rem, 6vw, 4.2rem);
  line-height: 1.04;
  letter-spacing: -.015em;
  margin: 0 0 22px;
}
.hero-lede {
  font-family: var(--font-serif);
  font-size: 1.15rem;
  line-height: 1.65;
  color: var(--muted);
  margin: 0;
  text-align: justify;
  hyphens: auto;
}
.hero-lede + .hero-lede { margin-top: .75em; }
.hero-photo {
  float: right;
  width: 260px;
  height: auto;
  aspect-ratio: 4 / 5;
  margin: 6px 0 24px 56px;
  object-fit: cover;
  filter: grayscale(.25) contrast(1.05);
}

/* The page list on the right, the active page's preview on the left. */
.home-index {
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 56px;
  padding-top: 48px;
}
.home-list { order: 2; }
/* Names line up on the right edge, away from the preview. */
.home-item {
  display: flex;
  justify-content: flex-end;
  padding: 18px 0;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  transition: color .2s ease, padding-right .25s ease;
}
.home-item:first-child { border-top: 1px solid var(--border); }
.home-item:hover { text-decoration: none; }
.home-item.is-active { color: var(--text); padding-right: 10px; }
.home-item-name {
  font-family: var(--font-serif);
  font-size: 1.6rem;
  /* A brass underline grows in under the hovered or focused name, so the
     list reads as links without arrows. */
  padding-bottom: 2px;
  background: linear-gradient(var(--accent), var(--accent)) right bottom / 0 1px no-repeat;
  transition: background-size .25s ease;
}
.home-item:hover .home-item-name,
.home-item:focus-visible .home-item-name { background-size: 100% 1px; }
/* The phone cards' image and keywords (see the 760px block). */
.home-item-img, .home-item-keys { display: none; }

.home-preview {
  display: grid;
  min-height: 340px;
}
/* Hidden previews are `visibility: hidden` too, so screen readers skip their keywords.
   Each preview lies on its page's image under a dark shade towards the bottom
   left, where the keywords sit (light on dark in both themes, see --media-*). */
.home-pv {
  grid-area: 1 / 1;
  position: relative;
  display: flex;
  align-items: flex-end;
  padding: 28px 32px;
  overflow: hidden;
  border-radius: var(--radius);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
}
.home-pv::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(20deg,
    color-mix(in srgb, var(--media-shade) 80%, transparent) 0%,
    color-mix(in srgb, var(--media-shade) 35%, transparent) 45%,
    color-mix(in srgb, var(--media-shade) 0%, transparent) 75%);
}
.home-pv-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.home-pv.is-active { opacity: 1; visibility: visible; transition: opacity .3s ease; }
.home-pv-keywords {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;  /* one line at full width; wraps only on narrower screens */
  white-space: nowrap;
  font-family: var(--font-serif);
  font-size: 1.08rem;
  line-height: 1.5;
  color: var(--media-text);
}
/* One line, dot-separated; the dot trails its keyword so a wrap never starts with one. */
.home-pv-keywords li:not(:last-child)::after { content: "\00b7"; margin: 0 .5em; color: var(--media-accent); }

/* ---------- CV ---------- */
.cv-section { margin-bottom: 52px; }
.section-title {
  font-size: 1.5rem;
  font-weight: 400;
  margin: 0 0 24px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.timeline { display: flex; flex-direction: column; gap: 30px; }
.entry { display: grid; grid-template-columns: 172px minmax(0, 1fr); gap: 24px; }
/* Long German compounds break instead of widening the page on phones. */
.entry-body { overflow-wrap: break-word; hyphens: auto; }
.entry-period { color: var(--muted); font-size: .92rem; font-weight: 500; padding-top: 3px; white-space: nowrap; }
.entry-title { font-size: 1.18rem; margin: 0 0 .2em; }
.entry-role { margin: 0 0 .5em; color: var(--accent); }
.entry-place { color: var(--muted); }
.entry-place::before { content: "· "; }
.entry-duration { display: block; margin-top: 2px; font-size: .82rem; font-weight: 400; opacity: .8; }
.entry-detail { margin: 0 0 .4em; }
.entry-bullets { margin: 0 0 .4em; padding-left: 1.1em; }
.entry-bullets li { margin-bottom: .25em; padding-left: .2em; }
.entry-bullets li::marker { color: var(--accent); }
.entry-extra { margin: 0 0 .4em; color: var(--muted); font-style: italic; }
.entry-links { margin: .6em 0 0; display: flex; gap: 18px; flex-wrap: wrap; font-size: .92rem; font-weight: 500; }

.entry-media-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 6px;
  color: var(--accent);
  vertical-align: middle;
  transition: transform .2s ease;
}
.entry-media {
  margin-top: 0;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height .4s cubic-bezier(.22, 1, .36, 1), opacity .3s ease, margin-top .4s ease;
}
.entry-media img,
.entry-media video { border-radius: var(--radius); border: 1px solid var(--border); max-width: 100%; width: 100%; display: block; }

.entry--has-media {
  cursor: pointer;
  margin: -8px -12px;
  padding: 8px 12px;
  border-radius: var(--radius);
  transition: background-color .25s ease;
}
.entry--has-media:hover,
.entry--has-media:focus-within,
.entry--has-media:focus {
  background: var(--bg-alt);
}
.entry--has-media:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--accent);
}
.entry--has-media:hover .entry-media-hint,
.entry--has-media:focus-within .entry-media-hint,
.entry--has-media:focus .entry-media-hint,
.entry--collapsible:hover .entry-media-hint,
.entry--collapsible:focus-within .entry-media-hint,
.entry--collapsible:focus .entry-media-hint {
  transform: translateY(-2px);
}
.entry--has-media:hover .entry-media,
.entry--has-media:focus-within .entry-media,
.entry--has-media:focus .entry-media {
  margin-top: 14px;
  max-height: 650px;
  opacity: 1;
}

.entry-expand-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 6px;
  color: var(--accent);
  vertical-align: middle;
  transition: transform .2s ease;
}
.entry-more {
  margin-top: 0;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  /* Closing is instant: a collapsing entry would otherwise shift the page while
     the browser scrolls the next focused entry into view, hiding it under the
     sticky header. Opening animates (see the open-state rule below). */
  transition: none;
}
.entry-more .entry-media { margin-top: 14px; }

.entry--collapsible {
  cursor: pointer;
  margin: -8px -12px;
  padding: 8px 12px;
  border-radius: var(--radius);
  transition: background-color .25s ease;
}
.entry--collapsible:hover,
.entry--collapsible:focus-within,
.entry--collapsible:focus {
  background: var(--bg-alt);
}
.entry--collapsible:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--accent);
}
.entry--collapsible:hover .entry-expand-hint,
.entry--collapsible:focus-within .entry-expand-hint,
.entry--collapsible:focus .entry-expand-hint {
  transform: translateY(2px);   /* points the way the entry opens */
}
.entry--collapsible:hover .entry-more,
.entry--collapsible:focus-within .entry-more,
.entry--collapsible:focus .entry-more {
  margin-top: 10px;
  max-height: 900px;
  opacity: 1;
  transition: max-height .4s cubic-bezier(.22, 1, .36, 1), opacity .3s ease, margin-top .4s ease;
}
.entry--collapsible:hover .entry-more .entry-media,
.entry--collapsible:focus-within .entry-more .entry-media,
.entry--collapsible:focus .entry-more .entry-media {
  max-height: 650px;
  opacity: 1;
}


.skills { margin: 0; display: flex; flex-direction: column; gap: 14px; }
.skill-row { display: grid; grid-template-columns: 180px 1fr; gap: 18px; }
.skill-row dt { font-weight: 600; color: var(--muted); }
.skill-row dd { margin: 0; }

.lang-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 12px 40px; }
.lang-list li { display: flex; gap: 10px; align-items: baseline; }
.lang-name { font-weight: 600; }
.lang-level { color: var(--muted); }

/* ---------- consulting project cards ---------- */
.projects { display: flex; flex-direction: column; }
/* Editorial case studies: no box, a hairline between projects, the image at a
   fixed 340×300 and the text as long as it needs. */
.project {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}
.project + .project { margin-top: 44px; padding-top: 44px; border-top: 1px solid var(--border); }
.project-media { background: var(--bg-alt); display: flex; align-items: center; justify-content: center; overflow: hidden; height: 300px; border-radius: var(--radius); }
.project-media img,
.project-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.project-info { min-width: 0; overflow-wrap: break-word; hyphens: auto; }
.project-client {
  margin: 0 0 .7em; color: var(--muted); font-weight: 600;
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
}
.project-title { font-size: 1.45rem; line-height: 1.25; letter-spacing: -.01em; margin: 0 0 .8em; hyphens: manual; }
.project-info p { margin: 0 0 1.2em; color: var(--muted); }
.project-info .project-client { margin-bottom: .7em; }
.project-info .project-result {
  margin: 0; color: var(--text);
  border-left: 2px solid var(--accent); padding: 2px 0 2px 16px;
}
.project-result strong {
  display: block; margin-bottom: .3em; color: var(--accent); font-weight: 600;
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
}

/* ---------- publication tiles (research) ---------- */
.pub-tiles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}
.pub-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 20px 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.pub-tile:has(.pub-main):hover {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}
.pub-year { color: var(--accent); font-size: .78rem; letter-spacing: .12em; margin-bottom: 8px; }
.pub-title { font-size: 1.12rem; line-height: 1.35; margin: 0 0 10px; }
.pub-main { color: inherit; }
.pub-main:hover { text-decoration: none; }
/* Stretched link: the whole tile is the main link's hit area. */
.pub-main::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.pub-main:focus-visible { outline: none; }
.pub-main:focus-visible::after { outline: 2px solid var(--accent); outline-offset: 2px; }
.pub-authors { margin: 0 0 4px; font-size: .9rem; color: var(--muted); }
.pub-authors strong { color: var(--text); font-weight: 500; }
.pub-venue { margin: 0; font-size: .88rem; color: var(--muted); font-style: italic; }
/* Pinned to the bottom so the icons line up across a row of tiles. */
.pub-links {
  margin-top: auto;
  padding-top: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  line-height: 1;
  color: var(--accent);
}
/* Above the stretched main link, so each icon takes its own hover and click. */
.pub-links a { position: relative; z-index: 1; color: inherit; }
.pub-links a:hover { text-decoration: none; }
.pub-pdf { display: inline-flex; transition: transform .2s ease; }
.pub-pdf svg { width: 16px; height: 16px; }
.pub-pdf:hover, .pub-pdf:focus-visible { transform: translateY(-2px); }

/* The ↗ that marks an outbound link, site-wide. It nudges up and to the right
   only while the pointer is on the arrow itself — the same small move everywhere. */
.link-arrow { display: inline-block; font-size: 1rem; transition: transform .2s ease; }
.link-arrow:hover { transform: translate(2px, -2px); }

/* ---------- lightbox ---------- */
.is-zoomable {
  cursor: zoom-in;
  outline-offset: -2px;
}
.is-zoomable:hover img,
.is-zoomable:hover video {
  transform: scale(1.02);
}
.is-zoomable img,
.is-zoomable video {
  transition: transform .35s cubic-bezier(.22, 1, .36, 1);
}

body.lightbox-open { overflow: hidden; }
.lightbox-sentinel { position: absolute; width: 1px; height: 1px; overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--media-shade) 0%, transparent);
  backdrop-filter: blur(0px);
  opacity: 0;
  visibility: hidden;   /* closed: out of the tab order and hidden from screen readers */
  pointer-events: none;
  transition: opacity .28s ease, background-color .28s ease, backdrop-filter .28s ease, visibility 0s linear .28s;
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  background: color-mix(in srgb, var(--media-shade) 60%, transparent);
  backdrop-filter: blur(4px);
  transition: opacity .28s ease, background-color .28s ease, backdrop-filter .28s ease;
}
.lightbox-card {
  position: relative;
  max-width: min(1000px, 85vw);
  max-height: 90vh;
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-hover);
  transform: scale(.92) translateY(8px);
  opacity: 0;
  transition: transform .32s cubic-bezier(.22, 1, .36, 1), opacity .28s ease;
}
.lightbox.is-open .lightbox-card {
  transform: scale(1) translateY(0);
  opacity: 1;
}
.lightbox-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  max-height: calc(90vh - 32px);
}
.lightbox-inner img,
.lightbox-inner video {
  display: block;
  max-width: 100%;
  max-height: calc(90vh - 32px);
  width: auto;
  height: auto;
  border-radius: var(--radius);
}
.lightbox-close {
  font-family: var(--font-sans);
  position: absolute;
  top: -14px;
  right: -14px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 1.3rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: background-color .18s ease, transform .18s ease, border-color .18s ease;
}
.lightbox-close:hover {
  background: var(--bg-alt);
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  transform: scale(1.08);
}

/* ---------- footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 28px 0;
  color: var(--muted);
  font-size: .9rem;
}
/* Three columns: ©, "Unlock more" centred, the links. */
.footer-inner { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px 24px; }
.footer-links { display: flex; align-items: center; justify-content: flex-end; gap: 20px; flex-wrap: wrap; }
.footer-unlock { display: inline-flex; align-items: center; gap: 6px; color: var(--accent); }
.footer-unlock:hover { text-decoration: underline; text-underline-offset: 3px; }
.footer-unlock.active { text-decoration: underline; text-underline-offset: 3px; }
.footer-lock { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.footer-unlock.is-unlocked .footer-lock { display: none; }
.footer-links > a { color: var(--muted); }
.footer-links > a:hover { color: var(--accent); }

/* Footer "Email" dropdown — a <details>, so it works without JS. */
.mail-menu { position: relative; }
.mail-menu > summary {
  cursor: pointer;
  color: var(--muted);
  list-style: none;          /* Firefox */
}
.mail-menu > summary::-webkit-details-marker { display: none; }
.mail-menu > summary::after { content: "\25BE"; margin-left: .35em; font-size: .85em; }
.mail-menu > summary:hover { color: var(--accent); }
.mail-menu[open] > summary { color: var(--text); }
/* Opens upward: the footer is the last thing on the page. */
.mail-menu-panel {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 0;
  z-index: 20;
  min-width: 232px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.mail-option { display: block; width: 100%; padding: 8px 10px; border: 0; border-radius: var(--radius); background: none; font: inherit; text-align: left; color: var(--muted); cursor: pointer; }
.mail-option:hover { background: var(--bg-alt); }
.mail-option-label { display: block; color: var(--text); font-weight: 500; }
.mail-option-addr { display: block; font-size: .88rem; }
/* Momentary confirmation after the address is copied to the clipboard. */
.mail-option.is-copied { background: var(--bg-alt); }
.mail-option.is-copied .mail-option-addr { color: var(--accent); font-weight: 500; }

/* ---------- consulting ---------- */
/* Clear space between the intro's contact box and the projects. */
.projects-title { margin-top: 64px; }

/* ---------- responsive ---------- */
@media (max-width: 760px) {
  .container { padding-inline: 16px; }
  .hero { padding: 48px 0 40px; }
  .hero-photo { width: 140px; margin-left: 20px; }
  /* Justified text beside the floated photo leaves wide gaps on a phone. */
  .hero-lede, .page-head .lead { text-align: left; }
  .home-index { grid-template-columns: 1fr; gap: 0; padding-top: 0; }
  /* No preview pane on a phone: each page is a card instead, its image under
     the same dark shade as the pane, name and keywords bottom left. */
  .home-preview { display: none; }
  .home-list { order: 0; display: grid; gap: 14px; }
  .home-item, .home-item.is-active {
    position: relative;
    flex-direction: column;
    justify-content: flex-end;
    align-items: flex-start;
    gap: 4px;
    aspect-ratio: 16 / 10;
    padding: 18px 20px;
    border: 0;
    border-radius: var(--radius);
    overflow: hidden;
    color: var(--media-text);
  }
  .home-item:first-child { border-top: 0; }
  .home-item::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(20deg,
      color-mix(in srgb, var(--media-shade) 85%, transparent) 0%,
      color-mix(in srgb, var(--media-shade) 40%, transparent) 50%,
      color-mix(in srgb, var(--media-shade) 0%, transparent) 80%);
  }
  .home-item-img { display: block; position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
  .home-item-name, .home-item-keys { position: relative; z-index: 1; }
  /* No hover on a phone: the underline is always there. */
  .home-item-name {
    font-size: 1.45rem;
    background-image: linear-gradient(var(--media-accent), var(--media-accent));
    background-size: 100% 1px;
    background-position: left bottom;
  }
  .home-item-keys { display: flex; flex-wrap: wrap; font-family: var(--font-serif); font-size: .95rem; line-height: 1.4; }
  .home-item-keys span:not(:last-child)::after { content: "\00b7"; margin: 0 .45em; color: var(--media-accent); }
  .entry { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .entry-period { padding-top: 0; }
  .entry-duration { display: inline; margin-left: .5em; }
  .entry-duration::before { content: "· "; }
  /* Own line on phones, so a long role never strands half a place name. */
  .entry-place { display: block; font-size: .92rem; }
  .entry-place::before { content: none; }
  .skill-row { grid-template-columns: 1fr; gap: 2px; }
  .pub-tiles { grid-template-columns: 1fr; }
  /* Five links + the language switch don't fit on one phone-width row.
     Brand, language switch and theme button keep row one; the links go on
     row two, so the switch never ends up stranded on a row of its own. */
  .nav { flex-wrap: wrap; height: auto; padding-block: 12px; gap: 10px 12px; }
  .brand { order: 0; margin-right: auto; }
  .lang-switch { order: 1; }
  .theme-toggle { order: 1; margin-left: -4px; }
  /* One row, never wrapping: spread over the width, and nav-fit.js shrinks
     --nav-size if the links would still not fit (any phone, any language). */
  .nav-links { order: 2; flex: 1 1 100%; min-width: 0; flex-wrap: nowrap; justify-content: space-between; gap: 10px; margin-left: 0; }
  .nav-links > a { font-size: var(--nav-size, .85rem); white-space: nowrap; }
  /* Footer stacked and centred: "Unlock more", the links, then ©. */
  .footer-inner { grid-template-columns: 1fr; justify-items: center; gap: 16px; }
  .footer-unlock { order: -1; }
  .footer-links { justify-content: center; }
  .footer-copy { order: 1; }
  /* Finger-sized tap areas (about 44px high) from an invisible ::before, so
     nothing moves. Horizontal overhang stays under half the gap between links. */
  .nav-links > a, .lang-switch, .theme-toggle, .footer-links > a, .footer-unlock, .mail-menu > summary { position: relative; }
  .nav-links > a::before, .lang-switch::before, .footer-links > a::before, .footer-unlock::before, .mail-menu > summary::before {
    content: "";
    position: absolute;
    inset: -10px -7px;
  }
  .nav-links > a::before { inset: -10px -5px; }   /* under half the 10px gap */
  /* Row-one targets stop above the row gap, so they never take taps meant for
     the links below. */
  .lang-switch::before { inset: -12px -12px -5px; }
  .theme-toggle::before { content: ""; position: absolute; inset: -7px -7px 0; }
  html { scroll-padding-top: 110px; }   /* the two-row phone header is ~95px */
}
/* Tablets: a narrower image column and a card as tall as its text, before the
   text column gets too narrow for the fixed card height. Phones: stacked. */
@media (max-width: 1024px) {
  .project { grid-template-columns: 240px minmax(0, 1fr); gap: 0 28px; }
  .project-media { height: auto; aspect-ratio: 340 / 300; }
}
@media (max-width: 760px) {
  .project { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .project + .project { margin-top: 32px; padding-top: 32px; }
}
/* Narrow phones: smaller still, so the German links stay on one line. */
@media (max-width: 359px) {
  .nav-links { gap: 5px; }
  .nav-links > a { font-size: var(--nav-size, .8rem); }
  .nav-links > a::before { inset: -10px -2px; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; transition: none !important; }
}

/* ---------- "Unlock more": the game, then the tour map (tours.html) ---------- */
/* The game, centred in the space between header and footer. */
.unlock-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(100dvh - 190px);
  padding-block: 40px 56px;
  text-align: center;
}
.unlock-game[hidden] { display: none; }
.unlock-title {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  letter-spacing: -.01em;
  text-wrap: balance;
}
.unlock-lead { margin: 12px 0 28px; color: var(--accent); font-size: 1.15rem; font-weight: 500; max-width: 52ch; text-wrap: balance; }
/* The personal note above the game prompt: a text block, not centred. */
.unlock-intro { max-width: 62ch; margin: 20px 0 8px; display: grid; gap: 12px; text-align: justify; hyphens: auto; }
.unlock-intro p { margin: 0; }
/* The arrow down to the games, centred on its own line. */
.unlock-arrow { display: block; margin-top: 6px; font-size: 1.3rem; line-height: 1; color: var(--accent); }
.unlock-games { width: min(720px, 100%); text-align: left; }
/* All six games in a grid, each under its sport's name. */
.unlock-games--all {
  width: min(1200px, 100%);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
  gap: 32px 24px;
}
.game-title {
  margin: 0 0 10px;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: 1.15rem;
  letter-spacing: -.005em;
  color: var(--accent);
}

/* Screen-reader copy of the message over the canvas. */
.game-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.game-stage { position: relative; }
.game-canvas {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 7;      /* jump games; steer games below */
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  touch-action: none;       /* dragging steers instead of scrolling */
  cursor: pointer;
}
.game-canvas:focus { outline: none; }
.game-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.game-panel--steer .game-canvas { aspect-ratio: 16 / 10; }
.unlock-games--all .game-canvas { aspect-ratio: 4 / 3; }
/* Messages (goal, fail, win) in a box over the faded canvas; long text
   scrolls inside the box rather than running past the canvas. */
.game-msg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  cursor: pointer;
}
.game-msg[hidden] { display: none; }
.game-msg-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-width: 36ch;
  max-height: 100%;
  overflow-y: auto;
  padding: 14px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  text-align: center;
}
/* The play button on the start and retry messages (the whole message is the
   click target; this only shows it). */
.game-play {
  width: 44px; height: 44px; margin-bottom: 4px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--shadow);
  transition: transform .2s;
}
.game-play::before {
  content: ""; display: block; width: 100%; height: 100%;
  background: var(--accent-contrast);
  clip-path: polygon(40% 30%, 40% 70%, 72% 50%);
}
.game-play[hidden] { display: none; }
.game-msg:hover .game-play { transform: scale(1.06); }
.game-msg strong { font-family: var(--font-serif); font-weight: 500; font-size: 1.1rem; line-height: 1.3; color: var(--text); }
.game-msg span { font-size: .85rem; line-height: 1.45; color: var(--muted); }
/* The win's button to the map: the site's brass button. */
.game-link { margin-top: 10px; box-shadow: var(--shadow); }
.game-link[hidden] { display: none; }
.game-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.game-hint { margin: 10px 0 0; font-size: .8rem; color: var(--muted); }

/* The map fills the page between header and footer. */
body.is-map { height: 100dvh; display: flex; flex-direction: column; }
body.is-map .unlock { flex: 1; min-height: 0; display: flex; }
.tm {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: clip;           /* not even scripts may scroll it (no hidden scrolling) */
  background: var(--map-land);
  border-block: 1px solid var(--border);
  font-size: 14px;
  line-height: 1.45;
  animation: tm-in .6s ease both;
}
@keyframes tm-in { from { opacity: 0; } }
.tm[hidden] { display: none; }
.tm button { font: inherit; color: inherit; }
.tm svg {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
/* .tm prefix: maplibre-gl.css, loaded later, sets .maplibregl-map relative. */
.tm .tm-map { position: absolute; inset: 0; }

/* Side panel (wide screens) / bottom sheet (phones). */
.tm-panel {
  position: absolute;
  z-index: 10;
  top: 12px; left: 12px; bottom: 12px;
  width: 384px;
  display: flex; flex-direction: column;
  background: var(--surface);   /* solid, so the sticky type headings hide the rows under them */
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.tm-grip { display: none; }
/* Opaque and above the list, so no scrolled row ever shows in the head. */
.tm-head { position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between; padding: 16px 12px 12px 18px; background: var(--surface); }
.tm-title {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 500; font-size: 1.35rem; letter-spacing: -.01em;
}
.tm-count { margin-left: 4px; font: 500 .9rem var(--font-sans); color: var(--faint); font-variant-numeric: tabular-nums; }
/* Phone-only parts of the sheet (see the phone block below). */
.tm-head-btn, .tm-head-back, .tm-filters-label, .tm-regions-sheet { display: none; }
.tm-view { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.tm-view[hidden] { display: none; }

.tm .chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0 14px; padding: 0 0 12px; border-bottom: 1px solid var(--border);
}
.tm .chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 10px 0 8px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: none; cursor: pointer;
  font-size: .78rem; font-weight: 500;
  transition: border-color .15s, opacity .15s;
}
.tm .chip:hover { border-color: var(--c); }
.tm .chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c); }
.tm .chip .n { color: var(--faint); font-variant-numeric: tabular-nums; }
.tm .chip[aria-pressed="false"] { opacity: .5; }
.tm .chip[aria-pressed="false"] .dot { background: none; box-shadow: inset 0 0 0 1.5px var(--c); }

/* No top padding: a sticky heading stops that far below the top, and rows
   would show above it. */
.tm .list { flex: 1; overflow-y: auto; padding: 0 6px 16px; outline: none; scrollbar-width: thin; }
.tm .group-head {
  position: sticky; top: -1px; z-index: 1;   /* -1px: no sliver of a row above it at fractional offsets */
  display: flex; align-items: baseline; gap: 8px;
  padding: 13px 10px 6px;
  margin-bottom: 4px;
  background: var(--surface);
  box-shadow: 0 1px 0 var(--border);   /* a clean edge where rows pass under it */
  font-size: .7rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted);
}
.tm .group-head .bar-c { width: 14px; height: 3px; border-radius: 2px; background: var(--c); align-self: center; }
.tm .group-head .by { margin-left: auto; font-weight: 500; letter-spacing: .02em; text-transform: none; color: var(--faint); }
.tm .row {
  position: relative;
  display: block; width: 100%; text-align: left;
  padding: 9px 10px 9px 22px; margin: 1px 0;
  border: 0; border-radius: var(--radius); background: none; cursor: pointer;
  transition: background .12s;
}
.tm .row::before {
  content: ""; position: absolute; left: 9px; top: 15px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--c);
  transition: transform .15s;
}
.tm .row:hover, .tm .row.is-hover, .tm .row.is-cursor { background: var(--bg-alt); }
.tm .row.is-hover::before, .tm .row.is-cursor::before { transform: scale(1.5); }
.tm .row.mixed::before { background: linear-gradient(90deg, var(--c) 50%, var(--c2) 50%); }
.tm .row-title { font-weight: 600; font-size: .9rem; line-height: 1.3; }
.tm .meta {
  display: flex; flex-wrap: wrap; gap: 2px 11px; margin-top: 3px;
  font-size: .76rem; color: var(--muted); font-variant-numeric: tabular-nums;
}
.tm .meta span { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.tm .meta svg { width: 12px; height: 12px; color: var(--faint); }
.tm .empty { padding: 32px 18px; color: var(--muted); text-align: center; }

/* Detail of the selected tour. */
.tm .detail { overflow-y: auto; padding: 0 18px 22px; scrollbar-width: thin; }
.tm .back {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  margin: 0 0 12px -6px; padding: 6px 8px; border: 0; border-radius: var(--radius);
  background: none; color: var(--muted); cursor: pointer; font-size: .82rem;
}
.tm .back:hover { color: var(--accent); background: var(--bg-alt); }
.tm .tags { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.tm .tag {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .7rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--c);
}
.tm .tag::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--c); }
.tm .detail h2 { margin: 6px 0 4px; font: 500 1.55rem/1.15 var(--font-serif); letter-spacing: -.015em; text-wrap: balance; }
.tm .sub { color: var(--muted); font-size: .82rem; }
.tm .kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 18px 0 6px; }
.tm .kpi { padding: 10px 10px 9px; border-radius: var(--radius); background: var(--bg-alt); min-width: 0; }
.tm .kpi .v { font: 500 1.08rem var(--font-serif); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tm .kpi .l { display: flex; align-items: center; gap: 4px; font-size: .68rem; color: var(--muted); }
.tm .kpi .l svg { width: 11px; height: 11px; }
.tm .peak { font-size: .76rem; color: var(--muted); margin: 2px 0 0; }
.tm .peak b { color: var(--text); font-weight: 600; }

.tm .profile { position: relative; margin: 16px -4px 4px; height: 140px; touch-action: pan-y; }
.tm .profile svg { width: 100%; height: 100%; stroke-width: 1; overflow: visible; }
.tm .profile .area { fill: url(#tm-pgrad); stroke: none; }
.tm .profile .line { stroke: var(--c); stroke-width: 1.6; fill: none; }
.tm .profile .sep { stroke: var(--border); stroke-dasharray: 2 3; }
.tm .profile .axis { fill: var(--faint); stroke: none; font: 500 10px var(--font-sans); }
.tm .profile .dayband { fill: var(--c); opacity: .12; stroke: none; }
.tm .profile .cur { stroke: var(--text); stroke-width: 1; opacity: .6; }
.tm .profile .curdot { fill: var(--c); stroke: var(--surface); stroke-width: 2; }
.tm .readout {
  position: absolute; top: -6px; transform: translateX(-50%);
  padding: 2px 7px; border-radius: var(--radius); pointer-events: none; white-space: nowrap;
  background: var(--text); color: var(--bg); font-size: .7rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.tm .actions { display: flex; gap: 8px; margin: 14px 0 6px; }
.tm-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  flex: 1; height: 36px; border-radius: var(--radius); cursor: pointer;
  border: 1px solid var(--border); background: none; font-size: .82rem; font-weight: 600;
  transition: background .15s, border-color .15s, color .15s;
}
.tm-btn:hover { border-color: var(--accent); color: var(--accent); }
.tm-btn.on { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.tm .empty .tm-btn { flex: none; padding: 0 16px; }

.tm .days { list-style: none; margin: 14px 0 0; padding: 0; border-top: 1px solid var(--border); }
.tm .day {
  display: grid; grid-template-columns: 30px 1fr; gap: 0 8px;
  padding: 10px 6px; margin: 0 -6px; border-radius: var(--radius); cursor: pointer;
}
.tm .day:hover, .tm .day.on { background: var(--bg-alt); }
.tm .day .no { font: 500 .95rem var(--font-serif); color: var(--faint); padding-top: 1px; }
.tm .day.on .no { color: var(--c); }
.tm .day .t { font-weight: 600; font-size: .85rem; line-height: 1.3; }

/* Over the map: region shortcuts along the top, controls on the right. */
.tm-regions {
  position: absolute; z-index: 5; top: 14px;
  left: 410px; right: 70px;
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none;
  pointer-events: none;
}
.tm-regions button {
  pointer-events: auto; flex: none;
  height: 30px; padding: 0 12px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--glass);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  font-size: .78rem; font-weight: 500; cursor: pointer; box-shadow: var(--shadow);
  transition: color .15s, border-color .15s;
}
.tm-regions button:hover { color: var(--accent); border-color: var(--accent); }
.tm-regions .n { color: var(--faint); margin-left: 4px; font-variant-numeric: tabular-nums; }
.tm-ctrls {
  position: absolute; z-index: 5; right: 14px; top: 14px;
  display: flex; flex-direction: column; gap: 1px;
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
  border: 1px solid var(--border); background: var(--border);
}
.tm-ctrl {
  display: grid; place-items: center; width: 38px; height: 38px;
  border: 0; background: var(--glass); cursor: pointer;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.tm-ctrl:hover { color: var(--accent); }
.tm-ctrl .tm-fill { fill: currentColor; }
.tm-ctrl-text { font: 600 .75rem var(--font-serif); letter-spacing: .02em; }
.tm-ctrl[aria-pressed="true"] { background: var(--accent); color: var(--accent-contrast); }
#tm-compass svg { transition: transform .2s; }

.tm-toast {
  position: absolute; z-index: 20; left: calc(50% + 198px); bottom: 28px; transform: translateX(-50%);
  max-width: min(440px, calc(100% - 32px)); padding: 9px 14px; border-radius: var(--radius);
  background: var(--text); color: var(--bg); font-size: .8rem; box-shadow: var(--shadow);
  pointer-events: none; transition: opacity .3s;
}
.tm-toast.fade { opacity: 0; }
.tm-tip {
  position: fixed; z-index: 20; pointer-events: none;
  max-width: 280px; padding: 7px 10px 8px; border-radius: var(--radius);
  background: var(--glass); border: 1px solid var(--border); box-shadow: var(--shadow);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.tm-tip .row-title { font-size: .84rem; }
.tm-tip .meta { margin-top: 2px; }

.tm .maplibregl-ctrl-attrib {
  background: var(--glass) !important; color: var(--faint); font-size: 10px;
  border-radius: var(--radius) 0 0 0;
}
.tm .maplibregl-ctrl-attrib a { color: var(--muted) !important; }
:root[data-theme="dark"] .tm .maplibregl-ctrl-attrib-button { filter: invert(.8); }
.tm .maplibregl-canvas:focus-visible { outline: none; }
.tm :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 760px) {
  .unlock-game { min-height: calc(100dvh - 240px); padding-block: 28px 40px; }
  .unlock-lead { margin-bottom: 20px; }
  .unlock-intro { text-align: left; }
  .game-canvas { aspect-ratio: 1 / 1; }
  .game-panel--steer .game-canvas { aspect-ratio: 3 / 4; }
  /* Six in a column: a little shorter, so a phone screen shows one whole game. */
  .unlock-games--all .game-canvas { aspect-ratio: 4 / 3; }
  .unlock-games--all .game-panel--steer .game-canvas { aspect-ratio: 1 / 1; }
  .game-msg { padding: 8px; }
  .game-msg-box { padding: 10px 12px; gap: 4px; }
  .game-msg strong { font-size: 1rem; }
  .game-msg span { font-size: .8rem; }
}
/* Phones, upright or turned sideways (tours.js uses the same query): the map
   takes everything below the header, with simpler controls. Upright phones
   then get the bottom sheet, sideways ones a left/right split (both below). */
@media (max-width: 760px), (max-height: 500px) {
  body.is-map .site-footer { display: none; }
  .tm-sheet-btn { display: none !important; }   /* the sheet's own, below */
  .tm { border-bottom: 0; }
  .tm-head { gap: 8px; padding: 2px 8px 6px 16px; }
  .tm-title { margin-right: auto; font-size: 1.15rem; }
  .tm-head-btn {
    position: relative;
    display: grid; place-items: center; width: 40px; height: 36px;
    border: 1px solid var(--border); border-radius: var(--radius); background: none; cursor: pointer;
  }
  .tm-head-btn[hidden] { display: none; }
  .tm-filter-btn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
  /* Some tour types switched off: a brass dot on the button. */
  .tm-filter-btn.is-filtered::after {
    content: ""; position: absolute; top: 5px; right: 5px;
    width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  }
  /* Tour types and regions only when asked for (the filter button), so the
     list keeps the room and the map stays clear. */
  .tm-regions { display: none; }
  .tm-filters { display: none; margin: 0 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
  .tm-panel.show-types .tm-filters { display: block; }
  .tm .tm-filters .chips { margin: 0; padding: 0; border: 0; }
  .tm-filters-label {
    display: block; margin: 8px 0 6px;
    font-size: .68rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted);
  }
  .tm-regions-sheet { display: flex; flex-wrap: wrap; gap: 6px; }
  .tm-regions-sheet button {
    height: 28px; padding: 0 10px; border: 1px solid var(--border); border-radius: var(--radius);
    background: none; cursor: pointer; font-size: .78rem; font-weight: 500;
  }
  .tm-regions-sheet .n { margin-left: 4px; color: var(--faint); font-variant-numeric: tabular-nums; }
  /* A tour open: back in the head bar instead of the title, the tour's card
     right under it (what the closed sheet shows), the details below. */
  .tm-panel.is-tour .tm-title, .tm-panel.is-tour .tm-filter-btn, .tm-panel.is-tour .tm-filters { display: none; }
  .tm-panel.is-tour .tm-head-back {
    display: inline-flex; align-items: center; gap: 4px; margin-right: auto;
    height: 36px; padding: 0 8px 0 2px; border: 0; background: none; cursor: pointer;
    font-size: .88rem; color: var(--muted);
  }
  .tm .detail .back { display: none; }
  /* A calm tour view: the type is a coloured dot before the title (the
     summits are on the map), one line of dates, one line of figures with
     icons instead of boxes (labels kept for screen readers), the profile,
     and only "Fly along" (the map has 3D, and opens on the whole tour). */
  .tm .detail { padding: 0 16px 16px; }
  .tm .tags, .tm .peak, #tm-act-fit, #tm-act-3d { display: none; }
  .tm .detail h2 { margin: 2px 0 2px; font-size: 1.2rem; }
  .tm .tm-card h2::before {
    content: ""; display: inline-block; width: 9px; height: 9px; margin: 0 9px 0 1px;
    border-radius: 50%; background: var(--c); vertical-align: .12em;
  }
  .tm .sub { font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Always one line: spread across the panel, the size shrinking with the
     panel's width (cqw), not the screen's. */
  .tm-panel { container-type: inline-size; }
  .tm .kpis { display: flex; flex-wrap: nowrap; justify-content: space-between; gap: 8px; margin: 10px 0 2px; }
  .tm .kpi { display: flex; flex-direction: row-reverse; align-items: center; gap: 4px; padding: 0; background: none; }
  .tm .kpi .v { font-size: clamp(.74rem, 3.8cqw, .95rem); }
  .tm .kpi .l { font-size: 0; color: var(--faint); }
  .tm .kpi .l svg { width: 13px; height: 13px; }
  .tm .profile { height: 96px; margin-top: 14px; }
  .tm .actions { justify-content: flex-end; margin: 4px 0 2px; }
  .tm .actions .tm-btn { flex: none; height: 30px; padding: 0 4px; border: 0; color: var(--muted); font-size: .78rem; gap: 5px; }
  .tm .actions .tm-btn.on { background: none; color: var(--accent); }
  .tm .days { margin-top: 10px; }
  .tm .day { padding: 7px 6px; }
  /* Zoom and rotate by gestures; compass and 3D stay. */
  #tm-zoom-in, #tm-zoom-out, #tm-rot-left, #tm-rot-right { display: none; }
  .tm-regions { left: 12px; right: 64px; top: 12px; }
  .tm-ctrls { right: 10px; top: 12px; }
  .tm-tip { display: none; }
}
/* Upright phones (tours.js uses the same query): the panel is a bottom sheet,
   closed, half or fully open, dragged or opened by its arrow button. */
@media (max-width: 760px) and (orientation: portrait) {
  .tm-panel {
    top: auto; left: 0; right: 0; bottom: 0;
    width: auto; height: 92%;
    border-radius: var(--radius) var(--radius) 0 0; border-bottom: 0;
    transform: translateY(calc(100% - var(--sheet-h, 172px)));
    transition: transform .28s cubic-bezier(.2, .8, .2, 1);
    touch-action: none;
  }
  .tm-panel.dragging { transition: none; }
  .tm .list, .tm .detail { touch-action: pan-y; }
  .tm-grip { display: block; padding: 8px 0 0; cursor: grab; }
  .tm-grip span { display: block; width: 38px; height: 4px; margin: 0 auto; border-radius: 2px; background: var(--border); }
  .tm-sheet-btn { display: grid !important; }
  .tm-sheet-btn svg { transition: transform .2s; }
  .tm-sheet-btn[aria-expanded="true"] svg { transform: rotate(180deg); }
  /* The sheet's hidden part (below the screen when it is half open) is
     added under the list and the tour, so both scroll to their very end. */
  .tm .list, .tm .detail { padding-bottom: calc(var(--sheet-hidden, 0px) + 16px); }
  .tm .maplibregl-ctrl-bottom-right { bottom: var(--sheet-h, 172px); }
}
/* Phones turned sideways: list and tour on the left, the map on the right. */
@media (max-width: 760px) and (orientation: landscape), (max-height: 500px) and (orientation: landscape) {
  .tm-panel { top: 8px; left: 8px; bottom: 8px; width: min(340px, 46%); }
  .tm-head { padding-top: 10px; }
}
/* Landscape phones: too short for square or portrait canvases. */
@media (max-height: 500px) {
  .game-canvas, .game-panel--steer .game-canvas, .unlock-games--all .game-canvas { aspect-ratio: 16 / 7; }
}
