/* ============================================================
   DESIGN TOKENS
   Colours sampled directly from the Adobe Portfolio screenshots.
   ============================================================ */
:root {
  --bg:            #222222;   /* page AND header - deliberately identical */
  --text:          #E3E3E3;   /* headings, nav */
  --text-body:     #D6D6D6;   /* paragraphs */
  --text-muted:    #9A9A9A;
  --surface:       #1F1F1F;   /* hero social circles */
  --surface-raised:#3A3A3A;   /* back-to-top */
  --overlay:       #EAEAEA;   /* category tile hover wash */
  --overlay-text:  #222222;
  --field:         #F8F8F8;
  --accent:        #033A71;
  --placeholder:   #2E2E2E;   /* dummy rectangles */
  --placeholder-line:#4E4E4E;

  --header-h: 108px;
  --pad-x: 60px;
  --ease: cubic-bezier(.22,.61,.36,1);

  --fs-hero: clamp(38px, 5.2vw, 72px);
  --fs-h1:   clamp(34px, 4.6vw, 64px);
  --fs-lead: clamp(17px, 1.35vw, 24px);
  --fs-body: clamp(16px, 1.15vw, 21px);
  --fs-nav:  clamp(16px, 1.1vw, 20px);
}

/* ============================================================
   RESET
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text-body);
  font-family: "Quicksand", "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
  font-weight: 500;
  font-size: var(--fs-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
h1, h2, h3 { margin: 0; color: var(--text); font-weight: 700; line-height: 1.1; }
p { margin: 0 0 1.1em; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* ============================================================
   HEADER  (fixed, opaque, same colour as page)
   ============================================================ */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  height: var(--header-h);
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  padding: 0 var(--pad-x);
  background: var(--bg);
  transition: height .32s var(--ease);
}

/* ---- Contracted header ----------------------------------------
   Shrinks once you scroll away from the top, showing only the mark.
   Returns to full size back at the top, or on hover.               */
.site-header.is-compact { height: 58px; }
/* width stays put: the lockup only fades, so the centre column keeps
   its size and the nav never slides sideways during the transition */
.site-header.is-compact .logo-full { opacity: 0; }
.site-header.is-compact .logo-mark { opacity: 1; }
.site-header.is-compact .nav-main  { font-size: clamp(14px, .95vw, 16px); }
.site-header.is-compact .nav-social svg { width: 19px; height: 19px; }

.site-header.is-compact:hover,
.site-header.is-compact:focus-within { height: var(--header-h); }
.site-header.is-compact:hover .logo-full,
.site-header.is-compact:focus-within .logo-full { opacity: 1; }
.site-header.is-compact:hover .logo-mark,
.site-header.is-compact:focus-within .logo-mark { opacity: 0; }
.site-header.is-compact:hover .nav-main,
.site-header.is-compact:focus-within .nav-main { font-size: var(--fs-nav); }
.site-header.is-compact:hover .nav-social svg,
.site-header.is-compact:focus-within .nav-social svg { width: 23px; height: 23px; }

@media (prefers-reduced-motion: reduce) {
  .site-header, .logo-full, .logo-mark { transition: none; }
}
.nav-main { display: flex; gap: 34px; font-size: var(--fs-nav); white-space: nowrap; }
.nav-main a { color: var(--text); opacity: .82; transition: opacity .2s var(--ease); }
.nav-main a:hover { opacity: 1; }
.nav-main a.is-active { font-weight: 700; opacity: 1; }

.logo { justify-self: center; display: grid; place-items: center; }
/* both marks share one cell so swapping them cannot shift the layout */
.logo-full, .logo-mark {
  grid-area: 1 / 1;
  height: auto; transition: opacity .28s var(--ease), width .32s var(--ease);
}
.logo-full { width: 178px; }
.logo-mark { width: 34px; opacity: 0; }

.nav-social { justify-self: end; display: flex; gap: 26px; align-items: center; }
.nav-social a { color: var(--text); opacity: .9; transition: opacity .2s var(--ease); }
.nav-social a:hover { opacity: 1; }
.nav-social svg { width: 23px; height: 23px; }

/* ---- Burger: a droplet anchored in the top-right corner ----
   Fixed to the screen, never part of the header, so it survives the
   header sliding away. The quarter-round bleeds off both edges, which
   is what gives it the droplet shape.                              */
/* A pill sliced down the middle by the screen edge: rounded cap on
   the left, flat against the border on the right. */
.burger {
  display: none;
  position: fixed; right: 0; top: 104px; z-index: 120;
  width: 66px; height: 54px; padding: 0;
  background: var(--surface-raised);
  border-radius: 999px 0 0 999px;
  transition: top .38s var(--ease), background .25s var(--ease),
              width .3s var(--ease), height .3s var(--ease),
              opacity .3s var(--ease);
}
.burger:hover, .burger:active { background: #4A4A4A; }

/* Once you are reading, the burger steps back: it tucks to the top,
   shrinks and goes translucent so it stops covering words, while
   staying findable. Full strength again at the top or once opened. */
body.scrolled .burger { width: 50px; height: 42px; opacity: .5; }
body.scrolled .burger-bars { width: 19px; }
body.scrolled .burger-bars span { width: 19px; height: 2px; margin: 4px 0; }
body.menu-open .burger { opacity: 1; width: 66px; height: 54px; }
body.menu-open .burger-bars { width: 26px; }
body.menu-open .burger-bars span { width: 26px; height: 3px; margin: 5px 0; }

.burger-bars {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: block; width: 26px;
  transition: width .3s var(--ease);
}
.burger-bars span {
  display: block; width: 26px; height: 3px; margin: 5px 0;
  background: var(--text); border-radius: 2px;
  transition: transform .28s var(--ease), opacity .2s var(--ease);
}
/* 8px, not 13: the bars' 5px margins collapse between siblings, so the
   gap between centres is height 3 + one 5px margin */
body.menu-open .burger-bars span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.menu-open .burger-bars span:nth-child(2) { opacity: 0; }
body.menu-open .burger-bars span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* Catches taps outside the panel so the menu can be dismissed without
   aiming for the X, and stops a stray tap hitting the page behind. */
.menu-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 105;
  background: rgba(8, 8, 8, .72);
  opacity: 0; pointer-events: none;
  transition: opacity .26s var(--ease);
}
body.menu-open .menu-backdrop { opacity: 1; pointer-events: auto; }

/* A strip the same height as the pill, sliding in from the right edge
   rather than dropping over the whole screen. */
.menu-panel {
  display: none;
  position: fixed; top: var(--burger-top, 104px); right: 0; z-index: 108;
  height: 54px; width: max-content;
  background: var(--surface-raised);
  border-radius: 999px 0 0 999px;
  flex-direction: row; align-items: center; justify-content: flex-end;
  gap: 26px;
  padding: 0 82px 0 30px;        /* right pad clears the pill */
  transform: translateX(100%);
  transition: transform .36s var(--ease), top .38s var(--ease);
  pointer-events: none;
}
.menu-panel a {
  display: block; width: auto; padding: 4px 2px;
  font-size: 17px; white-space: nowrap; color: var(--text);
}
.menu-panel a:active { background: rgba(255, 255, 255, .09); }
body.menu-open .menu-panel { transform: translateX(0); pointer-events: auto; }
body.menu-open { overflow: hidden; }

/* ============================================================
   HERO  (full viewport, fades out on scroll)
   ============================================================ */
.hero-wrap { position: relative; }

/* ---- Work drifting behind the greeting ---- */
.hero-bg {
  position: absolute; inset: 0; overflow: hidden;
  pointer-events: none; z-index: 0;
}
.star {
  --peak: .30;                  /* ceiling, so the text always wins */
  position: absolute;
  opacity: 0;
  transform: translate(-50%, -50%) scale(.55);
  will-change: opacity, transform;
}
/* the box takes the picture's own proportions, so square stickers and
   wide stills alike are shown whole rather than cropped to a ratio */
.star img { display: block; width: 100%; height: auto; border-radius: 6px; }
.star.is-running { animation-name: star-drift; animation-timing-function: var(--ease); }
/* in, dip, back up, then gone - scaling the whole way through */
/* One rise and one fall - the mid-animation dip was reading as the
   piece appearing twice. */
@keyframes star-drift {
  0%   { opacity: 0;            transform: translate(-50%, -50%) scale(.6); }
  16%  { opacity: var(--peak);  }
  68%  { opacity: var(--peak);  }
  100% { opacity: 0;            transform: translate(-50%, -50%) scale(1.26); }
}
/* the greeting and the cue sit above the drift */
.hero, .hero-chevron { position: relative; z-index: 1; }
.hero {
  height: 100vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  padding: var(--header-h) var(--pad-x) 0;
  will-change: opacity;
}
.hero h1 { font-size: var(--fs-hero); margin-bottom: .35em; }
.hero-sub { font-size: var(--fs-lead); color: var(--text-body); margin-bottom: 2.6em; }
/* A highlight sweeping left to right, so the eye is drawn to the cue
   that there is more below. Falls back to plain text where
   background-clip:text is unsupported. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-sub {
    background-image: linear-gradient(100deg,
      #8C8C8C 42%, #FFFFFF 50%, #8C8C8C 58%);
    background-size: 320% 100%;
    background-repeat: no-repeat;
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    animation: sub-sheen 2.8s linear infinite;
  }
}
@keyframes sub-sheen {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-sub { animation: none; }
}

.hero-social { display: flex; gap: 16px; }
.hero-social a {
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--surface); color: var(--text);
  display: grid; place-items: center;
  transition: background .25s var(--ease), transform .25s var(--ease);
}
.hero-social a:hover { background: #2E2E2E; transform: translateY(-2px); }
.hero-social svg { width: 19px; height: 19px; }

/* Three arrows lighting up one after another, downwards. Phones only -
   the desktop hero keeps its single hovering chevron. */
.hero-arrows {
  display: none; flex-direction: column; align-items: center;
  /* a finger-sized target, taken back out with margin so the arrows do
     not move; manipulation keeps a quick second tap from zooming */
  padding: 12px 30px; margin: -12px -30px;
  touch-action: manipulation;
}
.hero-arrows svg {
  display: block; width: 30px; height: 17px; color: var(--text-body);
  animation: arrow-chase 1.7s var(--ease) infinite;
}
.hero-arrows svg + svg { margin-top: -3px; }
.hero-arrows svg:nth-child(1) { animation-delay: 0s; }
.hero-arrows svg:nth-child(2) { animation-delay: .19s; }
.hero-arrows svg:nth-child(3) { animation-delay: .38s; }
/* the scale rides the same curve as the opacity, so each arrow swells
   as it lights up */
@keyframes arrow-chase {
  0%, 62%, 100% { opacity: .20; transform: scale(.86); }
  18%           { opacity: 1;   transform: scale(1.18); }
}

.hero-chevron {
  position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%);
  color: var(--text-body); opacity: .8;
  padding: 12px 26px;                /* bottom adjusted to match */
  touch-action: manipulation;
  animation: bob 2.4s var(--ease) infinite;
}
.hero-chevron svg { width: 52px; height: 30px; }
@keyframes bob {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, 9px); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-chevron { animation: none; }
}

/* ============================================================
   PLACEHOLDER RECTANGLES
   Rendered wherever `image` is null in data.js. Set a real path
   in the data and these disappear automatically.
   ============================================================ */
.thumb { position: relative; overflow: hidden; background: var(--placeholder); }
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.ratio-4x3  { aspect-ratio: 4 / 3; }
.ratio-16x9 { aspect-ratio: 16 / 9; }
.ratio-3x4  { aspect-ratio: 3 / 4; }
.ratio-1x1  { aspect-ratio: 1 / 1; }
.ratio-a4   { aspect-ratio: 1273 / 1800; }  /* portrait poster / A-series page */
.ratio-3x2  { aspect-ratio: 3 / 2; }        /* landscape spread */
/* image keeps its own shape - for sets with mixed dimensions */
.ratio-auto { aspect-ratio: auto; }
.ratio-auto img { height: auto; object-fit: contain; }
.ratio-auto .ph { position: static; min-height: 220px; }

.ph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: repeating-linear-gradient(45deg,
      transparent 0 16px,
      rgba(255,255,255,.045) 16px 32px);
  border: 1px dashed var(--placeholder-line);
}
.ph-label {
  font-size: 13px; letter-spacing: .1em; text-transform: uppercase;
  color: #B4B4B4; text-align: center; padding: 0 12px; max-width: 90%;
}

/* ============================================================
   WORK GRID  (category covers, near full-bleed)
   ============================================================ */
.work-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 36px; padding: 0 12px 120px;
}
.tile { position: relative; display: block; }
.tile-overlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--overlay);
  opacity: 0; transition: opacity .28s var(--ease);
}
.tile:hover .tile-overlay,
.tile:focus-visible .tile-overlay { opacity: .93; }
.tile-overlay h3 { font-size: clamp(20px, 1.8vw, 30px); color: var(--overlay-text); }
.tile-overlay span { margin-top: .5em; font-size: clamp(15px, 1.2vw, 20px); color: #4A4A4A; }

/* ============================================================
   CATEGORY PAGE
   ============================================================ */
.page-head { padding: calc(var(--header-h) + 90px) var(--pad-x) 84px; text-align: center; }
.page-head h1 { font-size: var(--fs-h1); }
.page-intro {
  max-width: 68ch; margin: 1.5em auto 0;
  font-size: var(--fs-lead); color: var(--text-body); line-height: 1.6;
}
.page-intro:empty { display: none; }

.gallery {
  display: grid;
  grid-template-columns: repeat(var(--gallery-cols, 2), 1fr);
  column-gap: 12px; row-gap: 52px;
  padding: 0 96px;
}
.gallery { align-items: start; }
.g-item { margin: 0; }
.g-media { position: relative; }
.g-media[data-video], [data-zoom] { cursor: pointer; }
.g-media[data-video]:focus-visible,
[data-zoom]:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }

/* Clickable stills: darken and name the action, so it reads as clickable */
[data-zoom]::after {
  content: ""; position: absolute; inset: 0;
  background: rgba(0,0,0,.45);
  opacity: 0; transition: opacity .25s var(--ease);
  pointer-events: none;
}
[data-zoom] .zoom-hint {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%) scale(.96);
  z-index: 2; pointer-events: none;
  padding: 9px 18px; border-radius: 999px;
  background: rgba(255,255,255,.92); color: #222;
  font-size: 13px; font-weight: 700; letter-spacing: .04em; white-space: nowrap;
  opacity: 0; transition: opacity .25s var(--ease), transform .25s var(--ease);
}
[data-zoom]:hover::after,
[data-zoom]:focus-visible::after { opacity: 1; }
[data-zoom]:hover .zoom-hint,
[data-zoom]:focus-visible .zoom-hint {
  opacity: 1; transform: translate(-50%,-50%) scale(1);
}

/* Touch devices get no hover, so state the affordance permanently */
@media (hover: none) {
  [data-zoom] .zoom-hint {
    opacity: 1; top: auto; bottom: 10px; transform: translate(-50%, 0) scale(1);
    background: rgba(255,255,255,.82); font-size: 12px; padding: 6px 13px;
  }
}
.g-embed { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; }
/* keep the placeholder caption clear of the play button */
.gallery .ph { align-items: end; }
.gallery .ph-label { padding-bottom: 16px; }

.g-caption { padding: 20px 2px 0; max-width: 58ch; }
.g-caption h3 { font-size: clamp(17px, 1.3vw, 21px); margin-bottom: .5em; }
.g-year { font-weight: 500; color: var(--text-muted); font-size: .82em; margin-left: .35em; }
.g-caption p { font-size: clamp(14px, 1vw, 16px); line-height: 1.6; color: var(--text-body); margin: 0; }

.play {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  width: 68px; height: 68px; border-radius: 50%;
  background: #fff; display: grid; place-items: center;
  transition: transform .25s var(--ease);
  pointer-events: none;
}
.g-item:hover .play { transform: translate(-50%,-50%) scale(1.07); }
.play svg { width: 24px; height: 24px; margin-left: 4px; color: #222; }

.divider-note {
  grid-column: 1 / -1;
  text-align: center; font-size: var(--fs-lead); color: var(--text-body);
  padding: 96px 0 44px;
}

/* ---- Feature block: text left, image right, grouped near the centre ---- */
.feature {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 48px; max-width: 1180px; margin: 0 auto;
  padding: 84px 0 64px;
}
/* text takes roughly three quarters of the row, so it reads in a few
   lines rather than a narrow column */
.feature-text {
  flex: 1 1 520px; max-width: none; margin: 0; text-align: left;
  font-size: var(--fs-lead); color: var(--text-body); line-height: 1.6;
}
.feature-media { flex: 0 0 min(250px, 24%); position: relative; overflow: hidden; }
.feature-media img { width: 100%; height: auto; display: block; }

/* ---- Compact: small thumbs, generous breathing room ---- */
.gallery.is-compact { row-gap: 110px; }
.gallery.is-compact .thumb { max-height: 360px; background: none; }
.gallery.is-compact .thumb img { height: 100%; object-fit: contain; object-position: left top; }

/* ---- Carousel: a rotating coverflow, one piece in focus ---- */
/* carousel pages trade heading space so a slide and its name fit on screen */
.carousel-page .page-head {
  padding: calc(var(--header-h) + 34px) var(--pad-x) 20px;
}
.carousel-page .page-head h1 { font-size: clamp(30px, 3.4vw, 46px); }
.carousel-page .page-intro {
  margin-top: .9em; font-size: clamp(15px, 1.1vw, 18px); max-width: 62ch;
}

.gallery.is-carousel {
  display: block; position: relative; padding: 0;
  --slide-w: min(380px, 58vw);   /* padding below derives from this, so
                                    the active slide lands dead centre */
}
.gallery.is-carousel .track {
  display: flex; gap: 18px;
  overflow-x: auto;   /* snapping is done in JS - native snap does not
                         re-snap after the loop's programmatic jumps */
  padding: 26px calc((100% - var(--slide-w)) / 2) 16px;
  perspective: 1400px; perspective-origin: 50% 45%;
  scrollbar-width: none;
}
.gallery.is-carousel .track::-webkit-scrollbar { display: none; }

.gallery.is-carousel .g-item {
  flex: 0 0 var(--slide-w);
  transform-style: preserve-3d;
  will-change: transform, opacity;
  transition: opacity .18s linear;
}
/* uniform slide height keeps the row tidy and fits image + name on screen */
.gallery.is-carousel .thumb {
  aspect-ratio: auto; height: min(34vh, 290px);
  background: none;
}
.gallery.is-carousel .thumb img { width: 100%; height: 100%; object-fit: contain; }
.gallery.is-carousel .g-caption {
  text-align: center; max-width: none; padding-top: 14px;
}
.gallery.is-carousel .g-caption p { font-size: 14px; }
/* only the piece in focus is fully legible */
.gallery.is-carousel .g-item:not(.is-focus) .g-caption { opacity: .45; }

/* Controls made to be tapped in a row. Without this, two quick taps read
   as a double tap and the browser zooms the page in under the user -
   "manipulation" keeps the tap and the scroll, and drops only that. It
   does not touch pinch zoom, which starts on the page, not on a button. */
.car-btn, .lb-nav, .lb-close, .to-top { touch-action: manipulation; }

.car-btn {
  position: absolute; top: 40%; transform: translateY(-50%); z-index: 5;
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--surface-raised); color: var(--text);
  display: grid; place-items: center; opacity: .85;
  transition: opacity .25s var(--ease), background .25s var(--ease);
}
.car-btn:hover { opacity: 1; background: #4A4A4A; }
.car-btn:disabled { opacity: .18; cursor: default; }
.car-btn svg { width: 22px; height: 22px; }
.car-prev { left: 18px; }
.car-next { right: 18px; }

/* ---- Lightbox ---- */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  background: #0E0E0E;
  display: none; place-items: center; padding: 56px 24px;
}
.lightbox.is-open { display: grid; }
.lb-figure { margin: 0; max-width: 100%; max-height: 100%; text-align: center; }
.lb-img {
  max-width: min(1400px, 94vw); max-height: 82vh;
  width: auto; height: auto; margin: 0 auto;
  /* the lightbox does its own pinch and pan, so the browser must not
     claim the gesture first */
  touch-action: none;
  transform-origin: center center;
}
.lb-img.is-zoomed { cursor: grab; }
.lb-caption { margin-top: 16px; color: var(--text-body); font-size: 15px; }

/* ---- Zoom hint ----
   Shown while the page (or an enlarged picture) is zoomed. A label, never
   a control: the gesture it names has to reach the page, so nothing here
   may swallow a tap. The dock is placed by JS onto the visual viewport
   and counter-scaled, so the hint keeps its size and stays on screen at
   any zoom. */
.zoom-dock {
  position: fixed; left: 0; top: 0; z-index: 240;
  transform-origin: 0 0;
  pointer-events: none;
}
.zoom-note {
  position: absolute; left: 0; top: 0; margin: 0;
  transform: translate(-50%, calc(-100% - 22px));
  pointer-events: none;            /* taps go straight through to the page */
  user-select: none;
  padding: 9px 18px;
  border-radius: 999px;
  /* just enough backing to stay legible over artwork */
  background: rgba(20, 20, 20, .72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: var(--text);
  font-size: 13px; font-weight: 500; letter-spacing: .01em; white-space: nowrap;
  opacity: 0; visibility: hidden;
  transition: opacity .22s var(--ease), visibility .22s var(--ease);
}
.zoom-dock.is-visible .zoom-note { opacity: 1; visibility: visible; }

@media (prefers-reduced-motion: reduce) {
  .zoom-note { transition: none; }
}
.lb-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 54px; height: 54px; border-radius: 50%;
  background: rgba(255,255,255,.12); color: #fff;
  display: grid; place-items: center;
  transition: background .25s var(--ease);
}
.lb-nav:hover { background: rgba(255,255,255,.26); }
.lb-nav[hidden] { display: none; }
.lb-nav svg { width: 24px; height: 24px; }
.lb-prev { left: 26px; }
.lb-next { right: 26px; }

.lb-close {
  position: absolute; top: 22px; right: 28px;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--surface-raised); color: var(--text);
  font-size: 28px; line-height: 1;
  display: grid; place-items: center;
}
.lb-close:hover { background: #4A4A4A; }

/* --- "You may also like" strip --- */
.also { padding: 150px 0 0; }
.also h2 { text-align: center; font-size: clamp(22px, 2vw, 30px); margin-bottom: 46px; }
.also-strip { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; }
.also-strip .tile-overlay h3 { font-size: clamp(14px, 1.1vw, 18px); }
.also-strip .tile-overlay span { font-size: 13px; }

/* ============================================================
   ABOUT
   ============================================================ */
.about {
  padding: calc(var(--header-h) + 40px) var(--pad-x) 140px;
  max-width: 1500px; margin: 0 auto;
}
.about h1 { font-size: var(--fs-h1); margin-bottom: 1.4em; padding-left: 76px; }
.about-grid {
  display: grid; grid-template-columns: minmax(0,1.35fr) minmax(0,.65fr);
  gap: 90px; align-items: start; padding-left: 76px;
}
/* sits above the grid, so the portrait lines up with the body text
   rather than with this opening line */
.about-intro {
  font-size: clamp(20px, 1.7vw, 29px); color: var(--text);
  margin: 0 0 2.2em; padding-left: 76px;
}
/* justified reads as a block of type rather than a ragged note;
   hyphenation stops it opening rivers between words */
.about-text p {
  max-width: 62ch;
  text-align: justify;
  hyphens: auto; -webkit-hyphens: auto;
}
/* Three bands, all lighter than the page, darkest on the outside:
   a thin dark ring, a thick mid-grey one, and a light mat innermost.
   Widths are variables so the phone can scale the whole frame down
   in one place and keep the proportion. */
/* Three bands of the same width and the same corner, darkest outside.
   Each is a nested box with its own padding and background rather than a
   border or a shadow: a border squares off its own inner corner and a
   shadow adds its spread to the radius, so neither can hold one curve
   across all three. */
.about-photo {
  width: 100%; max-width: 360px; position: relative;
  --band: 11px;
  --band-r: 9px;
  padding: var(--band);
  background: #4F4F4F;                /* outermost, darkest */
  border-radius: var(--band-r);
}
.about-photo .photo-band {
  padding: var(--band);
  background: #9A9A9A;                /* middle */
  border-radius: var(--band-r);
}
.about-photo .thumb {
  padding: var(--band);
  background: #C9C9C9;                /* innermost, lightest */
  border: 0;
  border-radius: var(--band-r);
  overflow: hidden;
}
/* square-round, not a pill - the picture carries the same corner */
.about-photo .thumb img { border-radius: var(--band-r); }

/* ============================================================
   LEGAL PAGES  (Impressum, Datenschutzerklärung)
   Plain, narrow and quiet - these are read, not looked at.
   ============================================================ */
.legal {
  padding: calc(var(--header-h) + 40px) var(--pad-x) 120px;
  max-width: 760px; margin: 0 auto;
}
.legal h1 { font-size: clamp(30px, 3.4vw, 46px); margin-bottom: 1.2em; }
.legal h2 {
  font-size: clamp(16px, 1.3vw, 19px); margin: 2.2em 0 .6em;
  color: var(--text);
}
.legal p { color: var(--text-body); line-height: 1.75; margin-bottom: 1em; }
.legal a { color: var(--text); border-bottom: 1px solid #555; }
.legal a:hover { border-bottom-color: var(--text); }
.legal code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92em; color: var(--text);
}
.legal-address { line-height: 1.9; }
.legal-missing {
  padding: 14px 18px; border-radius: 10px;
  background: var(--surface); color: var(--text);
}

/* The way to the Impressum, on every page. Deliberately unobtrusive -
   it is a legal necessity, not part of the work. */
.site-footer {
  display: flex; justify-content: center; align-items: center; gap: 10px;
  padding: 34px var(--pad-x) 40px;
  font-size: 13px; color: var(--text-muted);
}
.site-footer a { color: var(--text-muted); }
.site-footer a:hover { color: var(--text); }

/* ============================================================
   CONTACT
   ============================================================ */
.contact { padding: calc(var(--header-h) + 90px) var(--pad-x) 160px; text-align: center; }
.contact h1 { font-size: var(--fs-h1); margin-bottom: .9em; }
.contact-availability { font-size: var(--fs-lead); color: var(--text-body); margin-bottom: 3em; }

.email-row {
  display: inline-flex; align-items: center; gap: 14px; flex-wrap: wrap;
  justify-content: center; margin-bottom: .6em;
}
.email-link {
  font-size: clamp(22px, 2.4vw, 38px); font-weight: 700; color: var(--text);
  border-bottom: 2px solid transparent; transition: border-color .25s var(--ease);
}
.email-link:hover { border-bottom-color: var(--text); }
.copy-btn {
  width: 42px; height: 42px; border-radius: 50%; background: var(--surface);
  display: grid; place-items: center; color: var(--text);
  transition: background .25s var(--ease);
}
.copy-btn:hover { background: #2E2E2E; }
.copy-btn svg { width: 18px; height: 18px; }
.copy-toast { display: block; font-size: 14px; color: var(--text-muted); min-height: 1.5em; }

.cv-btn {
  display: inline-block; margin-top: 1.6em; padding: 14px 34px; border-radius: 999px;
  background: var(--accent); color: #fff; font-weight: 700;
  transition: filter .25s var(--ease);
}
.cv-btn:hover { filter: brightness(1.22); }

.profile-links { display: flex; justify-content: center; gap: 34px; flex-wrap: wrap; margin-top: 3.4em; }
.profile-links a { color: var(--text-body); border-bottom: 1px solid rgba(255,255,255,.22); }
.profile-links a:hover { color: var(--text); border-bottom-color: var(--text); }

/* ============================================================
   BACK TO TOP
   ============================================================ */
.to-top {
  position: fixed; right: 40px; bottom: 40px; z-index: 90;
  width: 58px; height: 58px; border-radius: 50%;
  background: var(--surface-raised); color: var(--text);
  display: grid; place-items: center;
  opacity: 0; visibility: hidden;
  transition: opacity .3s var(--ease), visibility .3s var(--ease), background .25s var(--ease);
}
.to-top.is-visible { opacity: .85; visibility: visible; }
.to-top:hover { opacity: 1; background: #4A4A4A; }
.to-top svg { width: 22px; height: 22px; }
.to-top-arrows { display: none; flex-direction: column; align-items: center; }
.to-top-arrows svg {
  display: block; width: 24px; height: 14px; color: var(--text);
  transform: rotate(180deg);
  animation: arrow-chase-up 1.7s var(--ease) infinite;
}
/* overlap between arrows only - a trailing negative margin would
   shrink the box below the glyphs and throw the centring off */
.to-top-arrows svg + svg { margin-top: -4px; }
/* bottom arrow first, so the chase travels upward */
.to-top-arrows svg:nth-child(1) { animation-delay: .38s; }
.to-top-arrows svg:nth-child(2) { animation-delay: .19s; }
.to-top-arrows svg:nth-child(3) { animation-delay: 0s; }
@keyframes arrow-chase-up {
  0%, 62%, 100% { opacity: .20; transform: rotate(180deg) scale(.86); }
  18%           { opacity: 1;   transform: rotate(180deg) scale(1.18); }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1180px) {
  :root { --pad-x: 36px; }
  .gallery { padding: 0 40px; }
  .about-grid { gap: 54px; padding-left: 0; }
  .about h1 { padding-left: 0; }
}

@media (max-width: 900px) {
  :root { --header-h: 92px; }
  .work-grid { grid-template-columns: repeat(2, 1fr); gap: 22px; }
  .gallery { --gallery-cols: 2; }
  .also-strip { grid-template-columns: repeat(3, 1fr); }
  .about-grid { grid-template-columns: 1fr; }
  /* the box loses 60px here, so the bands come down with it */
  .about-photo {
    max-width: 300px; margin-inline: auto;
    --band: 9px; --band-r: 7px;
  }
}

@media (max-width: 680px) {
  :root { --pad-x: 20px; --header-h: 84px; }

  /* Phone header: just the logo, centred. The page links live in the
     burger, which is fixed to the corner and is not part of this bar. */
  .site-header { grid-template-columns: 1fr auto 1fr; }
  /* one source of truth for where the pill and its strip sit */
  body { --burger-top: 104px; }
  body.scrolled { --burger-top: 10px; }
  .burger { display: block; top: var(--burger-top); }
  .menu-panel { display: flex; }
  .menu-backdrop { display: block; }

  /* fades out rather than sliding, so the logo leaves like the text.
     On pages without a hero this is driven by scroll direction. */
  .site-header.is-hidden { opacity: 0; pointer-events: none; }
  .site-header { transition: height .32s var(--ease), opacity .3s var(--ease); }
  .nav-main, .nav-social { display: none; }
  /* display:none drops those two out of the grid, so the logo must be
     pinned to the middle column or it slides into the first one */
  .logo { display: grid; grid-column: 2; }
  .logo-full { width: 116px; }
  .logo-mark { width: 30px; }
  .site-header.is-compact { height: 56px; }

  /* hero: arrows replace the mail icon and the bottom chevron */
  .hero-social, .hero-chevron { display: none; }
  .hero-arrows { display: flex; }
  .hero { height: 100svh; }          /* ignores the address bar, so nothing jumps */
  .hero-sub { margin-bottom: 1.8em; }

  /* ---- Categories as a swipeable carousel -------------------
     The labels can no longer wait for a hover that never comes,
     so the overlay is always on - same look as the desktop
     hover state, with the cover showing through behind it.   */
  .work-grid.is-carousel {
    position: relative; padding: 0;
    --slide-w: min(300px, 78vw);
    transition: opacity .4s var(--ease);
    /* fills the screen below the hero so the carousel sits centred
       rather than clinging to the bottom of the page */
    min-height: 100svh;
    display: flex; flex-direction: column; justify-content: center;
  }
  /* deliberately quiet - it is a hint, not a headline, and should not
     pull attention off the arrows or the carousel */
  .work-note {
    display: block; text-align: center; margin: 24px auto 0; max-width: 30ch;
    font-size: 12.5px; line-height: 1.45; color: #7C7C7C;
  }
  .work-grid.is-carousel .track {
    display: flex; gap: 16px;
    overflow-x: auto; overscroll-behavior-x: contain;
    padding: 6px calc((100% - var(--slide-w)) / 2) 14px;
    perspective: 1200px; perspective-origin: 50% 45%;
    scrollbar-width: none;
  }
  .work-grid.is-carousel .track::-webkit-scrollbar { display: none; }
  .work-grid.is-carousel .tile {
    flex: 0 0 var(--slide-w);
    transform-style: preserve-3d; will-change: transform, opacity;
  }
  /* The wash is carried by the background rather than the element's own
     opacity, so the artwork shows through while the label stays at full
     strength - fading the whole layer would have taken the text with it.
     The halo keeps the title readable over a light patch of cover. */
  .work-grid.is-carousel .tile-overlay {
    opacity: 1;
    background: rgba(234, 234, 234, .58);
  }
  .work-grid.is-carousel .tile-overlay h3,
  .work-grid.is-carousel .tile-overlay span {
    text-shadow: 0 1px 12px rgba(255, 255, 255, .9),
                 0 0 4px rgba(255, 255, 255, .8);
  }
  .work-grid.is-carousel .car-btn { top: 50%; }
  .work-grid.is-carousel .car-prev { left: 4px; }
  .work-grid.is-carousel .car-next { right: 4px; }
  .work-grid { grid-template-columns: 1fr; gap: 16px; }
  .gallery { --gallery-cols: 1; padding: 0 20px; row-gap: 34px; }
  .gallery.is-compact { row-gap: 64px; }
  .feature { grid-template-columns: 1fr; gap: 28px; padding: 56px 0 40px; }
  .feature-media { max-width: 260px; margin: 0 auto; }
  .feature-text { text-align: center; }
  .car-btn { width: 42px; height: 42px; }
  .car-prev { left: 6px; }
  .car-next { right: 6px; }
  .also-strip { grid-template-columns: repeat(2, 1fr); }
  /* Lightbox: the arrows sat on top of the picture on a narrow screen,
     so they move to a row underneath it. Swiping works too. */
  .lightbox { padding: 60px 12px 96px; }
  .lb-img { max-height: 66vh; max-width: 94vw; }
  .lb-nav {
    top: auto; bottom: 22px; transform: none;
    width: 50px; height: 50px;
  }
  .lb-prev { left: 50%; margin-left: -60px; }
  .lb-next { right: 50%; margin-right: -60px; }
  .lb-close { top: 14px; right: 14px; }

  /* About: the desktop indent made this line look centred on a phone */
  .about-intro { padding-left: 0; }

  .to-top { right: 20px; bottom: 20px; width: 52px; height: 52px; }
  .to-top-icon { display: none; }
  .to-top-arrows { display: flex; }
  .play { width: 54px; height: 54px; }
}

/* Phones: the centred logo no longer fits between nav and icons. */
@media (max-width: 520px) {
  /* the logo now stays: the burger freed up the room it needed */
  .logo-full { width: 104px; }
  .about h1, .page-head h1 { font-size: 34px; }
}
