﻿/* Reset & base ------------------------------------------------------------ */
* {
  box-sizing: border-box;
}
:root {
  font-family: "Times New Roman", Times, serif;
  font-style: italic;
  color: #000;
}
body {
  margin: 0;
  font-family: inherit;
  background: #000;
  color: #fff;
}
nav, button, a, h1, p {
  font-family: inherit;
}
/* Visually hidden but still present for screen readers/crawlers — used for
   the page's one real <h1>, which carries no visual weight of its own here
   (the design communicates identity through the hero grid instead). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Native scrollbars are hidden everywhere in favor of the custom dot
   indicator (.scroll-indicator below) — kept in sync with real scroll
   position by script.js, not just a cosmetic swap. */
html {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar {
  display: none;
}
.info-overlay-panel,
.lightbox-info {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.info-overlay-panel::-webkit-scrollbar,
.lightbox-info::-webkit-scrollbar {
  display: none;
}

/* Scroll indicator — a single white dot tracking scroll position along the
   right edge, replacing the page's (now hidden) native scrollbar. Only
   shown while the page/panel is actually scrollable. */
.scroll-indicator {
  position: fixed;
  top: calc(var(--header-height, 96px) + 1rem);
  bottom: 1rem;
  right: 0.6rem;
  width: 2px;
  z-index: 300;
  pointer-events: none;
}
.scroll-indicator[hidden] {
  display: none;
}
.scroll-indicator-dot {
  position: absolute;
  left: 50%;
  top: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #fff;
  transform: translateX(-50%);
}

/* Navigation --------------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
}
/* `sticky` detaches once its containing block runs out of room, which shows
   up as the nav scrolling away right at the bottom of the page — `fixed`
   keeps it pinned unconditionally. That takes it out of flow, so the page
   content needs a matching top offset (--header-height, measured in JS
   since the nav's real height varies with viewport width) to not start out
   hidden underneath it. */
.page-shell {
  padding-top: var(--header-height, 96px);
}
.primary-nav {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 0;
  width: 100%;
  height: auto;
  padding: 1rem;
  z-index: 100;
}
.nav-right {
  margin-left: auto;
  display: flex;
  gap: 1.5rem;
}
@media (min-width: 1024px) {
  .primary-nav {
    gap: 2.5rem;
    padding: 2rem 4rem;
    height: 110px;
  }
  .nav-right {
    gap: 2.5rem;
  }
}
.nav-button {
  font-size: 3.4vw;
  letter-spacing: 0.08em;
  background: transparent;
  border: none;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  font-weight: 1000;
}
@media (min-width: 1024px) {
  .nav-button {
    font-size: 1.7rem;
  }
}
.nav-button:hover {
  color: #999;
}

/* Project index list — replaces the old "INDEX" nav link; every project's
   number, linking straight to that project's lightbox, listed under INFO.
   Fixed to the viewport (out of flow, so it doesn't add to the header's
   height and push the hero grid down) and vertically centered on screen;
   right-aligned horizontally, unchanged from before. */
.project-index-list {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.25rem;
  padding: 0 1rem 1rem;
}
@media (min-width: 1024px) {
  .project-index-list {
    padding: 0 4rem 1.5rem;
  }
}
body.lightbox-open .project-index-list {
  display: none;
}
.project-index-link {
  font-family: inherit;
  font-style: italic;
  font-weight: 1000;
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  background: transparent;
  border: none;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  padding: 0;
}
@media (min-width: 1024px) {
  .project-index-link {
    font-size: 1rem;
  }
}
.project-index-link:hover {
  color: #999;
}
.project-index-link--disabled {
  color: #555;
  cursor: default;
}
.project-index-link--disabled:hover {
  color: #555;
}

/* Hero grid (homepage) — featured hero images stacked in a column; a few
   are pulled out as overlays positioned beside another tile ---------------- */
.hero-grid {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 3rem;
  width: 100%;
  padding: 3rem;
}
.hero-tile {
  position: relative;
  user-select: none;
  -webkit-user-select: none;
}
.hero-tile img,
.hero-tile video {
  display: block;
  width: 100%;
  height: auto;
  -webkit-user-drag: none;
}
.hero-tile[data-code="0012"] img {
  filter: saturate(0.7);
}
.hero-marquee {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  padding: 0.36rem 0;
  white-space: nowrap;
}
.hero-marquee-track {
  display: inline-flex;
  width: max-content;
  animation: hero-marquee-scroll 16s linear infinite;
}
.hero-marquee-track span {
  display: inline-block;
  white-space: nowrap;
  font-weight: 1000;
  font-size: 1.26rem;
  letter-spacing: 0.05em;
  color: #000;
}
@keyframes hero-marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
.hero-tile-code {
  position: absolute;
  top: 0;
  left: 100%;
  margin-left: 0.03rem;
  writing-mode: vertical-rl;
  font-weight: 1000;
  font-size: 1rem;
  letter-spacing: 0.05em;
  color: #ddd95f;
  white-space: nowrap;
  pointer-events: none;
}
.hero-tile-date {
  font-weight: 700;
  font-size: 0.85em;
  opacity: 0.7;
}

/* Back button — fixed to the bottom-right corner of the page, only shown
   once a project's lightbox is open. Styled like the nav bar buttons
   (transparent, no border/box) rather than as a standalone pill. --------- */
.back-button {
  position: fixed;
  right: 1rem;
  bottom: 1.75rem;
  z-index: 150;
  background: transparent;
  color: inherit;
  border: none;
  padding: 0;
  font-family: inherit;
  font-weight: 1000;
  font-size: 1rem;
  letter-spacing: 0.08em;
  cursor: pointer;
}
@media (min-width: 1024px) {
  .back-button {
    right: 4rem;
    font-size: 1.5rem;
  }
}
.back-button:hover {
  color: #999;
}
.back-button[hidden] {
  display: none;
}

/* Project lightbox — fullscreen overlay opened by clicking a hero image.
   One slide at a time (the hero, then each media item, then a project-info
   slide); clicking anywhere advances to the next, looping back to the hero
   once the rotation completes. Sits below the sticky nav and back button
   (z-index) so both stay usable as the way out. ---------------------------- */
.project-lightbox {
  position: fixed;
  inset: 0;
  z-index: 140;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 4rem 2rem;
  background: #000;
  cursor: pointer;
}
.project-lightbox[hidden] {
  display: none;
}
.lightbox-slide {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
}
.lightbox-slide img,
.lightbox-slide video {
  display: block;
  max-width: 88vw;
  max-height: 76vh;
  width: auto;
  height: auto;
  -webkit-user-drag: none;
}
.lightbox-slide img.slide-inverted {
  filter: invert(1);
}
.lightbox-slide video {
  cursor: default;
}
.lightbox-media {
  position: relative;
  display: flex;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
}
/* Same treatment as .hero-tile-code on the landing page — vertical,
   rotated text tucked into the top-right corner of the image. Hidden until
   script.js adds .is-loaded to the wrapper (once the image/video has
   actually loaded), so it doesn't pop in ahead of still-loading media. */
.lightbox-caption {
  position: absolute;
  top: 0;
  left: 100%;
  margin-left: 0.03rem;
  writing-mode: vertical-rl;
  font-weight: 1000;
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  color: #ddd95f;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.15s ease-out;
  pointer-events: none;
}
.lightbox-media.is-loaded .lightbox-caption {
  opacity: 1;
}
.lightbox-counter {
  flex: none;
  font-weight: 1000;
  font-size: 1rem;
  letter-spacing: 0.05em;
}

/* Project-info slide — always the second slide, right after the hero. */
.lightbox-info {
  max-width: 640px;
  max-height: 76vh;
  overflow-y: auto;
  padding: 0 1rem;
  text-align: left;
  cursor: default;
}
.lightbox-info-title {
  margin: 1.5em 0 1rem;
  font-size: clamp(1.25rem, 3vw, 2rem);
  font-weight: 1000;
  letter-spacing: -0.01em;
}
.lightbox-info-meta {
  opacity: 0.7;
  margin: 0 0 1rem;
}
.lightbox-info p {
  margin: 0 0 1rem;
  font-weight: 700;
  line-height: 1.5;
}
.lightbox-info p:last-child {
  margin-bottom: 0;
}
.lightbox-info hr {
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
  margin: 1rem 0;
}
.lightbox-info-empty {
  opacity: 0.5;
  font-style: italic;
}

body.lightbox-open,
body.info-open {
  overflow: hidden;
}

/* Info overlay — opened from the nav's INFO link; the page behind stays
   fully visible (no backdrop tint/blur) since every piece of text carries
   its own tight black background instead (.text-highlight below). Holds a
   text area on top and a CV area below. Independent of the project
   lightbox, so it layers above everything including the nav that opens it.
   ---------------------------------------------------------------------- */
.info-overlay {
  position: fixed;
  inset: 0;
  z-index: 260;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 2rem;
  background: transparent;
  cursor: pointer;
}
.info-overlay[hidden] {
  display: none;
}
.info-overlay-panel {
  width: min(880px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2rem;
  padding: 1rem;
  color: #ddd95f;
  font-size: 1.2rem;
  text-align: left;
  cursor: default;
}
/* Hugs a solid black box tightly around the glyphs of whatever it wraps
   (not the whole paragraph's box) — box-decoration-break: clone re-applies
   that box per line, so wrapped/multi-line text stays hugged line by line
   instead of one rectangle spanning the gaps between lines. */
.text-highlight {
  background: #000;
  padding: 0.1em 0.35em;
  border-radius: 2px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.info-overlay-text p {
  margin: 0 0 1rem;
  font-weight: 1000;
  font-size: 1.6rem;
  letter-spacing: 0.05em;
  line-height: 1.5;
}
.info-overlay-text p:last-child {
  margin-bottom: 0;
}
.info-overlay-text a {
  color: inherit;
  text-decoration: underline;
}
.info-overlay-text a:hover {
  opacity: 0.7;
}
.info-overlay-cv {
  padding-top: 2rem;
}
.info-overlay-cv-heading {
  margin: 0 0 0.75rem;
  font-weight: 1000;
  font-size: 1.4rem;
  letter-spacing: 0.05em;
  color: #fff;
}
.info-overlay-cv-entry {
  display: flex;
  font-size: 1.2rem;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 0.4rem;
  padding: 0.1em 0.35em;
  background: #000;
  border-radius: 2px;
  color: #fff;
  font-weight: 1000;
  letter-spacing: 0.05em;
}
.info-overlay-cv-entry:last-child {
  margin-bottom: 0;
}
.info-overlay-cv-entry-year {
  opacity: 0.7;
}
.info-overlay-empty {
  opacity: 0.5;
  font-style: italic;
}
.info-overlay-impressum {
  padding-top: 2rem;
  font-size: 0.8em;
  color: #fff;
}
.info-overlay-impressum-heading {
  margin: 1.25rem 0 0.4rem;
  font-weight: 1000;
  letter-spacing: 0.05em;
}
.info-overlay-impressum-heading:first-child {
  margin-top: 0;
}
.info-overlay-impressum-body p {
  margin: 0 0 0.75rem;
  font-weight: 700;
  line-height: 1.5;
}
.info-overlay-impressum-body p:last-child {
  margin-bottom: 0;
}
.info-overlay-impressum-body a {
  color: inherit;
  text-decoration: underline;
}
.info-overlay-impressum-body a:hover {
  opacity: 0.7;
}

/* Mobile (narrow/vertical) layout ------------------------------------------
   Desktop relies on absolute pixel positioning (hero overlays) baked for
   wide viewports. Below this width, that collapses into a single stacked
   column instead — same visual language (italic serif, marquee titles),
   just reflowed; the lightbox itself is already responsive. Nothing above
   this block is touched. */
@media (max-width: 768px) {
  .hero-grid {
    flex-direction: row;
    flex-wrap: wrap;
    align-content: flex-start;
    padding: 1.25rem;
    gap: 1.75rem;
  }
  /* Every tile is shrunk by a fixed gutter (not just a % cut) so there's
     always room beside the image for the vertical code/date label instead
     of it landing on top of the image. */
  .hero-tile {
    position: relative !important;
    top: auto !important;
    left: auto !important;
    width: calc(100% - 1.75rem) !important;
    flex: 1 1 calc(100% - 1.75rem) !important;
    margin-left: 0 !important;
  }
  .hero-marquee {
    padding: 0.2rem 0;
  }
  .hero-marquee-track span {
    font-size: 0.69rem;
  }
  .hero-tile-code {
    font-size: 0.65rem;
  }

  /* Every hero stays in its original order (no CSS `order` reshuffling) —
     just varied width + alternating left/right inset so the stack doesn't
     read as a rigid, uniform, full-viewport-width column. */
  .hero-tile[data-code="0011"] {
    flex: 0 1 calc(92% - 1.75rem) !important;
    width: calc(92% - 1.75rem) !important;
  }
  .hero-tile[data-code="0012"] {
    flex: 0 1 calc(65% - 1.75rem) !important;
    width: calc(65% - 1.75rem) !important;
  }
  .hero-tile.hero-tile--portrait[data-code="0006"] {
    flex: 0 1 calc(74% - 1.75rem) !important;
    width: calc(74% - 1.75rem) !important;
  }
  .hero-tile[data-code="0008"] {
    flex: 0 1 calc(92% - 1.75rem) !important;
    width: calc(92% - 1.75rem) !important;
  }
  .hero-tile[data-code="0004"] {
    flex: 0 1 calc(82% - 1.75rem) !important;
    width: calc(82% - 1.75rem) !important;
  }
  .hero-tile.hero-tile--portrait[data-code="0010"] {
    flex: 0 1 calc(68% - 1.75rem) !important;
    width: calc(68% - 1.75rem) !important;
    margin-left: 0 !important;
  }
  .hero-tile[data-code="0005"] {
    flex: 0 1 calc(90% - 1.75rem) !important;
    width: calc(90% - 1.75rem) !important;
  }

  .project-lightbox {
    padding: 5.5rem 1.25rem 6.5rem;
  }
  .lightbox-slide img,
  .lightbox-slide video {
    max-width: 80vw;
    max-height: 62vh;
  }
  /* The rotated caption sits to the right of the image on desktop, but that
     runs off the edge of a narrow viewport — move it to the left instead,
     and shrink the image above just enough to leave it room to fit. Capped
     to the image's own height so a caption longer than that wraps into a
     second (third, ...) column instead of overflowing past top/bottom. */
  .lightbox-caption {
    left: auto;
    right: 100%;
    margin-left: 0;
    margin-right: 0.2rem;
    /* `max-height: 100%` would be the obvious choice, but percentage heights
       on an absolutely positioned element only resolve against an ancestor
       with a *definite* height — .lightbox-media's height is auto (sized by
       the image), so that computes to "none" and never wraps. Matching the
       same viewport-relative cap the image itself uses (see
       .lightbox-slide img/video above) is a concrete number instead. */
    max-height: 62vh;
    font-size: 0.6rem;
    white-space: normal;
  }
  .lightbox-info {
    /* Narrower than the 92vw the image/caption get — the fixed
       .project-index-list sits at the right edge regardless of what's open,
       so the text needs to stop short of it instead of running underneath. */
    max-width: 74vw;
    max-height: 62vh;
    padding: 0;
    font-size: 0.9rem;
  }

  .info-overlay {
    padding: 1.25rem;
  }
  .info-overlay-panel {
    max-height: 88vh;
    padding: 0.5rem;
  }

  .back-button {
    font-size: 0.9rem;
  }

  .project-index-list {
    top: 60%;
  }
}
