/* ==========================================================================
   Nicolas Emmenegger — components
   Header, footer, buttons, concert list, discography, timeline, contact.
   ========================================================================== */

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--t-mid) var(--ease-out),
              border-color var(--t-mid) var(--ease-out),
              backdrop-filter var(--t-mid) var(--ease-out);
}
/* Transparent over the hero, then solid once you are into the content. It
   changes weight, never position — the nav is how you leave this page. */
.site-header.is-stuck {
  background: color-mix(in oklab, var(--c-bg) 88%, transparent);
  backdrop-filter: blur(14px) saturate(1.1);
  border-bottom-color: var(--c-line);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  min-height: 4.75rem;
}

.logo {
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 0.1em;
  flex: none;
}
/* The wordmark is set exactly like the name on the arrival page — the sans,
   light, uppercase and widely tracked. One voice in the top bar instead of a
   serif wordmark arguing with a sans navigation beside it. */
.logo-text {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: clamp(0.72rem, 1.15vw, 0.9rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  line-height: 1.35;
  display: flex;
  flex-direction: column;
}
.logo-text b { font-weight: 400; }
.logo-sub {
  font-size: 0.68em;
  font-weight: 400;
  letter-spacing: 0.3em;
  color: var(--c-text-mute);
  margin-top: 0.5em;
}

@media (max-width: 700px) {
  .logo-text { letter-spacing: 0.16em; }
}
.logo:hover .logo-text b { color: var(--c-accent); }

.nav { display: flex; align-items: center; gap: var(--sp-5); }

.nav-list {
  display: flex;
  align-items: center;
  gap: clamp(var(--sp-4), 2.2vw, var(--sp-6));
}

.nav-link {
  font-size: var(--fs-sm);
  font-weight: 300;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--c-text-soft);
  padding-block: var(--sp-2);
  position: relative;
  white-space: nowrap;
}
.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--c-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-mid) var(--ease-out);
}
.nav-link:hover, .nav-link[aria-current="page"] { color: var(--c-text); }
.nav-link:hover::after, .nav-link[aria-current="page"]::after { transform: scaleX(1); }

.header-actions { display: flex; align-items: center; gap: var(--sp-2); }

.icon-btn {
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--c-line);
  color: var(--c-text-soft);
  text-decoration: none;
  transition: border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              background-color var(--t-fast) var(--ease-out);
}
.icon-btn svg { width: 1.15rem; height: 1.15rem; }
.icon-btn:hover {
  color: var(--c-accent);
  border-color: var(--c-accent);
  background: var(--c-glow);
}

.nav-toggle { display: none; }

@media (max-width: 860px) {
  .nav-toggle { display: grid; }
  .nav-list {
    position: fixed;
    inset: 0;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-5);
    background: var(--c-bg);
    padding: var(--sp-9) var(--gutter);
    transform: translateY(-100%);
    visibility: hidden;
    transition: transform var(--t-mid) var(--ease-in-out), visibility var(--t-mid);
  }
  .nav-list.is-open { transform: translateY(0); visibility: visible; }
  .nav-list .nav-link { font-size: var(--fs-lg); letter-spacing: 0.04em; }
  .header-actions { z-index: 1; }
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: 0.72em 1.5em;
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid var(--c-line-str);
  color: var(--c-text);
  background: transparent;
  white-space: nowrap;
  transition: background-color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.btn svg { width: 1.05em; height: 1.05em; flex: none; }

.btn--primary {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-bg-sink);
}
.btn--primary:hover {
  background: var(--c-accent-soft);
  border-color: var(--c-accent-soft);
  color: var(--c-bg-sink);
}

.btn--ghost:hover { border-color: var(--c-accent); color: var(--c-accent); }

.btn--sm { padding: 0.55em 1.1em; font-size: var(--fs-xs); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
}

/* ==========================================================================
   Section heads
   ========================================================================== */

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
  margin-bottom: var(--sp-7);
}
.title-block { max-width: 46ch; }
.title-block > * + * { margin-top: var(--sp-3); }
.title-block p { color: var(--c-text-soft); }

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: min(88svh, 780px);
  display: flex;
  align-items: center;
  padding-block: var(--sp-9) var(--sp-8);
  overflow: hidden;
}

/* Stage light: one soft brass wash from the upper left, one cold rim from the
   right. Pure CSS — no image to download, and it never blocks the text. */
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  z-index: var(--z-bg);
  pointer-events: none;
  border-radius: 50%;
  filter: blur(90px);
}
.hero::before {
  width: 60vw; height: 60vw;
  max-width: 900px; max-height: 900px;
  top: -22%; left: -14%;
  background: radial-gradient(circle, rgba(208,169,74,0.20), transparent 68%);
}
.hero::after {
  width: 46vw; height: 46vw;
  max-width: 700px; max-height: 700px;
  right: -12%; bottom: -18%;
  background: radial-gradient(circle, rgba(127,147,181,0.14), transparent 70%);
}

.hero-inner { position: relative; z-index: var(--z-content); }

/* ---- Arrival page --------------------------------------------------------
   One screen: the photograph, and the name over it. The header sits on top of
   it and the footer waits below the fold, so the first thing anyone sees is
   him and nothing else.

   100svh rather than 100vh: on a phone, vh is the tall viewport with the
   browser chrome retracted, so a vh hero is always taller than the screen and
   the name sits half under the address bar until you scroll.
   -------------------------------------------------------------------------- */
.hero--arrival {
  min-height: 100svh;
  margin-top: -4.75rem;        /* up behind the transparent header */
  padding-block: 6rem var(--sp-8);
  align-items: flex-end;
}
.hero--arrival::before,
.hero--arrival::after { opacity: 0.55; }

.hero-photo {
  position: absolute;
  inset: 0;
  z-index: var(--z-bg);
  background: var(--c-bg) center / cover no-repeat;
  opacity: 0;
  transition: opacity var(--t-slow) var(--ease-out);
}
.hero-photo.is-in { opacity: 1; }

/* A scrim in three parts, so the page is legible over any photograph without
   having to know what is in it: heavy at the bottom for the name, a band
   across the top so the navigation survives a bright sky or a white studio
   wall, and a soft wash from the left to seat the wordmark. */
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(10, 11, 14, 0.8) 0%, rgba(10, 11, 14, 0.35) 9%, transparent 20%),
    linear-gradient(to top, var(--c-bg) 2%, rgba(10, 11, 14, 0.55) 42%, rgba(10, 11, 14, 0.2) 100%),
    linear-gradient(to right, rgba(10, 11, 14, 0.55), transparent 60%);
}

/* The name is set small and wide rather than large: at this size the sans is
   a caption on the photograph instead of a headline over it, which is the
   quieter, more modern way round. The tracking is what carries it — letter-
   spaced capitals read as a wordmark even at 1rem. */
.hero-name {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: clamp(0.82rem, 1.6vw, 1.05rem);
  line-height: 1.5;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  /* The tracking adds a trailing gap after the last letter; pull it back so
     the block still aligns to the gutter. */
  margin-right: -0.42em;
}
.hero-name .line { display: block; }

/* A hairline above the name, the width of a bow. Ties it to the photograph
   rather than leaving it floating. */
.hero-name::before {
  content: "";
  display: block;
  width: 3.5rem;
  height: 1px;
  background: var(--c-accent);
  margin-bottom: var(--sp-4);
}

@media (max-width: 700px) {
  .hero--arrival { align-items: flex-end; padding-bottom: var(--sp-7); }
  .hero-name { letter-spacing: 0.3em; margin-right: -0.3em; }
}

.hero-title {
  font-size: var(--fs-3xl);
  letter-spacing: -0.02em;
  margin-top: var(--sp-5);
}
.hero-title .line { display: block; }
.hero-sub {
  margin-top: var(--sp-5);
  font-size: var(--fs-md);
  color: var(--c-text-soft);
  max-width: 52ch;
  line-height: 1.6;
}
.hero-actions { margin-top: var(--sp-7); }

.hero-scroll {
  margin-top: var(--sp-8);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-mute);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.hero-scroll::after {
  content: "";
  width: 3rem;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

/* ==========================================================================
   Concerts
   ========================================================================== */

.concert-list { border-top: 1px solid var(--c-line); }

.concert {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr) auto;
  gap: var(--sp-5) var(--sp-6);
  align-items: start;
  padding-block: var(--sp-6);
  border-bottom: 1px solid var(--c-line);
  transition: background-color var(--t-fast) var(--ease-out);
}
.concert:hover { background: color-mix(in oklab, var(--c-surface) 55%, transparent); }

.concert--past { color: var(--c-text-mute); }
.concert--past .concert-title { color: var(--c-text-soft); }
.concert--past .concert-day { color: var(--c-text-mute); }

/* Date block — the thing a visitor actually scans for. */
.concert-when { font-family: var(--font-mono); line-height: 1.25; }
.concert-day {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--c-accent);
  letter-spacing: 0;
}
.concert-month {
  display: block;
  margin-top: 0.15em;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-soft);
}
.concert-time {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--c-text-mute);
  letter-spacing: 0.06em;
}

.concert-body > * + * { margin-top: var(--sp-2); }
.concert-title { font-size: var(--fs-md); font-family: var(--font-display); }
.concert-venue { color: var(--c-text-soft); font-size: var(--fs-sm); }
.concert-with { color: var(--c-text-mute); font-size: var(--fs-sm); }

.programme {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--c-text-soft);
  border-left: 1px solid var(--c-line);
  padding-left: var(--sp-4);
}
.programme li + li { margin-top: var(--sp-1); }
.programme .composer { color: var(--c-text); }

.concert-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--sp-2);
}

.tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-accent);
  border: 1px solid color-mix(in oklab, var(--c-accent) 45%, transparent);
  padding: 0.25em 0.7em;
}
.tag--mute { color: var(--c-text-mute); border-color: var(--c-line); }

@media (max-width: 760px) {
  .concert {
    grid-template-columns: 5.5rem minmax(0, 1fr);
    gap: var(--sp-4);
  }
  .concert-actions {
    grid-column: 2;
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
  }
  .concert-day { font-size: var(--fs-md); }
}

/* The next date, given its own weight on the home page. */
.next-concert {
  border: 1px solid var(--c-line);
  background: linear-gradient(150deg,
              color-mix(in oklab, var(--c-surface) 90%, transparent),
              var(--c-bg-raise));
  padding: clamp(var(--sp-5), 4vw, var(--sp-8));
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-6);
  align-items: center;
}
.next-concert .concert-day { font-size: var(--fs-xl); }
.next-concert-meta > * + * { margin-top: var(--sp-3); }
@media (max-width: 700px) {
  .next-concert { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Recordings
   ========================================================================== */

.release-list > * + * { margin-top: var(--sp-8); }

.release {
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: clamp(var(--sp-5), 4vw, var(--sp-8));
  align-items: start;
  padding-bottom: var(--sp-8);
  border-bottom: 1px solid var(--c-line);
}
.release:last-child { border-bottom: 0; padding-bottom: 0; }

@media (max-width: 720px) {
  .release { grid-template-columns: 1fr; }
  .sleeve { max-width: 260px; }
}

/* Sleeve. If a cover image exists it sits on top; if it does not — or fails to
   load — the typographic sleeve underneath is what you see. Either way there
   is never a broken image on the page. */
.sleeve {
  position: relative;
  aspect-ratio: 1;
  width: 100%;
  background:
    linear-gradient(155deg, var(--c-surface-2), var(--c-bg-sink));
  border: 1px solid var(--c-line);
  display: grid;
  place-items: center;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.sleeve::after {
  /* A single brass hairline, like the rule on a record sleeve. */
  content: "";
  position: absolute;
  inset: var(--sp-4);
  border: 1px solid color-mix(in oklab, var(--c-accent) 22%, transparent);
  pointer-events: none;
}
.sleeve-fallback {
  text-align: center;
  padding: var(--sp-5);
  font-family: var(--font-display);
}
.sleeve-initials {
  font-size: clamp(2rem, 8vw, 3.2rem);
  color: var(--c-accent);
  letter-spacing: 0.08em;
}
.sleeve-year {
  margin-top: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wider);
  color: var(--c-text-mute);
}
/* The cover starts transparent and is revealed by its own load event, so a
   missing file simply leaves the sleeve underneath showing. */
.sleeve img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity var(--t-mid) var(--ease-out);
}

.release-head > * + * { margin-top: var(--sp-2); }
.release-title { font-size: var(--fs-lg); }
.release-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-mute);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
}
.release-note { margin-top: var(--sp-4); color: var(--c-text-soft); max-width: 58ch; }
.release-links { margin-top: var(--sp-5); }

/* Track listing — collapsed by default so a long disc does not push the next
   release off the screen. */
.tracks { margin-top: var(--sp-5); border-top: 1px solid var(--c-line); }
.tracks > summary {
  cursor: pointer;
  list-style: none;
  padding-block: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-mute);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.tracks > summary::-webkit-details-marker { display: none; }
.tracks > summary::after {
  content: "";
  width: 0.5em; height: 0.5em;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translateY(-0.15em);
  transition: transform var(--t-fast) var(--ease-out);
}
.tracks[open] > summary::after { transform: rotate(-135deg) translateY(-0.15em); }
.tracks > summary:hover { color: var(--c-accent); }

.track {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr) auto;
  gap: var(--sp-4);
  padding-block: var(--sp-2);
  font-size: var(--fs-sm);
  border-top: 1px solid var(--c-line);
}
.track-no { font-family: var(--font-mono); color: var(--c-text-mute); }
.track-dur { font-family: var(--font-mono); color: var(--c-text-mute); }
.track-name { color: var(--c-text-soft); }
.track-name .composer { color: var(--c-text); }

/* One video on the home page shouldn't run the full width of the page. */
.home-video { max-width: 760px; }

/* Video */
.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: var(--sp-6);
}
.video-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--c-bg-sink);
  border: 1px solid var(--c-line);
}
.video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.video-caption { margin-top: var(--sp-3); }
.video-caption h3 { font-size: var(--fs-md); }
.video-caption p { font-size: var(--fs-sm); color: var(--c-text-mute); margin-top: var(--sp-1); }

/* ==========================================================================
   Photos
   ========================================================================== */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  grid-auto-rows: clamp(150px, 18vw, 230px);
  gap: var(--sp-4);
}

.photo-item {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--c-line);
  background: var(--c-surface);
  padding: 0;
  cursor: zoom-in;
  display: block;
  width: 100%;
  height: 100%;
}
/* A tall photograph gets two rows rather than being cropped to a letterbox. */
.photo-item--tall { grid-row: span 2; }

.photo-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out), opacity var(--t-mid) var(--ease-out);
}
.photo-item:hover img { transform: scale(1.04); }
.photo-item::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid transparent;
  transition: border-color var(--t-fast) var(--ease-out);
}
.photo-item:hover::after,
.photo-item:focus-visible::after { border-color: var(--c-accent); }

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: color-mix(in oklab, var(--c-bg-sink) 95%, transparent);
  display: grid;
  grid-template-rows: 1fr auto;
  padding: clamp(var(--sp-4), 4vw, var(--sp-7));
  gap: var(--sp-4);
}
.lightbox[hidden] { display: none; }

.lightbox-stage {
  display: grid;
  place-items: center;
  min-height: 0;
}
.lightbox-stage img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-shadow: var(--shadow-lg);
}

.lightbox-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.lightbox-caption { font-size: var(--fs-sm); color: var(--c-text-soft); max-width: 60ch; }
.lightbox-caption .credit { display: block; color: var(--c-text-mute); font-size: var(--fs-xs); margin-top: var(--sp-1); }
.lightbox-count {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--c-text-mute);
}
.lightbox-controls { display: flex; align-items: center; gap: var(--sp-3); }

.lightbox-close {
  position: absolute;
  top: clamp(var(--sp-4), 4vw, var(--sp-7));
  right: clamp(var(--sp-4), 4vw, var(--sp-7));
}

/* ==========================================================================
   Biography / history
   ========================================================================== */

.bio-layout {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: clamp(var(--sp-6), 5vw, var(--sp-9));
  align-items: start;
}
@media (max-width: 860px) {
  .bio-layout { grid-template-columns: 1fr; }
  .portrait-frame { max-width: 320px; }
}

/* No portrait — either none was supplied, or the file was missing and the
   column removed itself. The prose then takes the full width instead of
   sitting beside an empty column. */
.bio-layout:not(:has(.bio-portrait)) { grid-template-columns: minmax(0, 1fr); }

.portrait-frame {
  position: relative;
  border: 1px solid var(--c-line);
  padding: var(--sp-3);
  background: var(--c-bg-raise);
}
.portrait-frame img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

/* Timeline — the history proper. A single brass stave down the left with the
   years hanging off it. */
.timeline {
  position: relative;
  padding-left: var(--sp-7);
  border-left: 1px solid var(--c-line);
}
.tl-item { position: relative; padding-bottom: var(--sp-7); }
.tl-item:last-child { padding-bottom: 0; }
.tl-item::before {
  content: "";
  position: absolute;
  left: calc(var(--sp-7) * -1 - 1px);
  top: 0.55em;
  width: var(--sp-5);
  height: 1px;
  background: var(--c-accent);
  opacity: 0.7;
}
.tl-year {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--c-accent);
}
.tl-title { font-size: var(--fs-md); margin-top: var(--sp-2); }
.tl-text { margin-top: var(--sp-2); color: var(--c-text-soft); max-width: 60ch; }

/* Awards, teachers and other short lists set as a definition-style table. */
.fact-list { border-top: 1px solid var(--c-line); }
.fact {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: var(--sp-4);
  padding-block: var(--sp-4);
  border-bottom: 1px solid var(--c-line);
}
.fact dt {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  color: var(--c-accent);
}
.fact dd { color: var(--c-text-soft); }
.fact dd strong { color: var(--c-text); font-weight: 500; }
@media (max-width: 560px) {
  .fact { grid-template-columns: 1fr; gap: var(--sp-1); }
}

/* Press quotes */
.quote-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--sp-5);
}
.quote {
  border: 1px solid var(--c-line);
  background: var(--c-bg-raise);
  padding: var(--sp-6);
  position: relative;
}
.quote p {
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-style: italic;
  line-height: 1.5;
  color: var(--c-text);
}
.quote footer {
  margin-top: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--c-text-mute);
}

/* ==========================================================================
   Cards / contact
   ========================================================================== */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: var(--sp-5);
}
.card {
  border: 1px solid var(--c-line);
  background: var(--c-bg-raise);
  padding: var(--sp-6);
  transition: border-color var(--t-fast) var(--ease-out),
              transform var(--t-mid) var(--ease-out);
}
.card:hover { border-color: var(--c-line-str); transform: translateY(-2px); }
.card h3 { font-size: var(--fs-md); }
.card p { margin-top: var(--sp-3); color: var(--c-text-soft); font-size: var(--fs-sm); }

.contact-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(var(--sp-6), 5vw, var(--sp-9));
  align-items: start;
}
@media (max-width: 820px) { .contact-layout { grid-template-columns: 1fr; } }

.contact-lines { border-top: 1px solid var(--c-line); }
.contact-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-5);
  padding-block: var(--sp-4);
  border-bottom: 1px solid var(--c-line);
  text-decoration: none;
}
.contact-line .mono-label { flex: none; }
.contact-line span:last-child { text-align: right; word-break: break-word; }
a.contact-line:hover { color: var(--c-accent); }

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty {
  border: 1px dashed var(--c-line-str);
  padding: var(--sp-8) var(--sp-6);
  text-align: center;
  color: var(--c-text-mute);
}
.empty p + p { margin-top: var(--sp-3); }

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  margin-top: var(--sp-8);
  border-top: 1px solid var(--c-line);
  background: var(--c-bg-sink);
  padding-block: var(--sp-8) var(--sp-6);
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: var(--sp-7);
}
@media (max-width: 760px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 460px) { .footer-grid { grid-template-columns: 1fr; } }

.footer-col h4 {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--c-text-mute);
  margin-bottom: var(--sp-4);
}
.footer-col ul > li + li { margin-top: var(--sp-2); }
.footer-col a { text-decoration: none; color: var(--c-text-soft); font-size: var(--fs-sm); }
.footer-col a:hover { color: var(--c-accent); }

/* Social links: marks only. The name lives in aria-label and title, so a
   screen reader and a hovering mouse both still get "Instagram —
   @nicolasemmenegger" even though the footer stays quiet. */
.icon-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.icon-row > li + li { margin-top: 0; }

.footer-bar {
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--c-line);
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  font-size: var(--fs-xs);
  color: var(--c-text-mute);
}
