/* =====================================================================
   OTTO JAKOB — site.css: layout and components. Pairs with tokens.css
   (palette / type / motion). Plain CSS, no framework.
   ===================================================================== */

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

/* The gallery uses a generous gutter aligned to the wordmark / utilities. */
:root { --gutter: 44px; }
@media (max-width: 720px) { :root { --gutter: 20px; } }

/* =====================================================================
   HEADER — sticky across the catalogue scroll. Desktop: the masthead row
   holds the wordmark (left) and EN/DE + icons (right); the section links
   (.mainnav, a separate header child) are laid over that row, centred in
   the gap between the two groups; the subnav rows sit below. The sticky
   header is the containing block for the absolutely-placed .mainnav.
   The compact (hamburger) layout is in the media query further down.
   ===================================================================== */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper);
}
.site-header--noir { position: absolute; left: 0; right: 0; background: transparent; }
/* Overlay: the landing header over a LIGHT hero (an editorial poster) — floats
   transparent like --noir but keeps the default ink colours. */
.site-header--overlay { position: absolute; left: 0; right: 0; background: transparent; }

.masthead {
  display: flex; align-items: center;
  gap: 24px; padding: 25px var(--gutter);     /* a ~77px band */
}
.navtoggle { display: none; }              /* hamburger: mobile only */
.wordmark {
  order: 0;
  display: inline-flex; align-items: center; line-height: 1;
}
/* The brand SVG, painted via CSS mask so a single-colour mark takes the
   header's text colour: ink on light headers, gold on the noir landing. The
   SVG's intrinsic ratio is 56.69:14.17 (~4:1); height ≈ the old 39px cap. */
.wordmark__mark {
  display: block; height: 26px; width: calc(26px * 56.69 / 14.17);
  background-color: var(--ink);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.site-header--noir .wordmark__mark { background-color: var(--gold-light); }

/* Section links: a thin box on the masthead's centre line (38px down, ~15px
   tall), inset symmetrically by the wider side group (the wordmark) so the
   links centre on the viewport like the subnav rows and can never overlap
   the wordmark or the EN/DE + icons, even with the longer German labels. */
.mainnav {
  position: absolute; top: 31px; left: 266px; right: 266px;
  display: flex; align-items: center; justify-content: center;
}
.nav-sections { display: flex; align-items: center; gap: 36px; }
.mainnav a { line-height: 1; }
.nav-sections a {
  font-family: var(--sans); font-weight: var(--w-med);
  font-size: var(--fs-nav); letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-soft); padding-bottom: 2px;
  border-bottom: 1px solid transparent; white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.nav-sections a:hover { color: var(--ink); }
.nav-sections a.is-active { color: var(--ink); font-weight: var(--w-semi); }
.site-header--noir .nav-sections a { color: rgba(244,241,233,.74); }
.site-header--noir .nav-sections a:hover { color: var(--on-noir); }
.site-header--noir .nav-sections a.is-active { color: var(--on-noir); font-weight: var(--w-semi); }

/* Language switch — margin-left: auto sends it and the icons after it to the
   far right, leaving the middle band for the overlaid section nav. */
.langswitch { order: 2; margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.langswitch a {
  font-family: var(--sans); font-weight: var(--w-med);
  font-size: var(--fs-nav); letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-faint); padding-bottom: 2px;   /* faded: the active one is bold ink */
  border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.langswitch__sep { font-family: var(--sans); font-size: var(--fs-nav); color: var(--ink-faint); }
.langswitch a.is-current { color: var(--ink); font-weight: var(--w-semi); }
.site-header--noir .langswitch a { color: rgba(244,241,233,.45); }
.site-header--noir .langswitch__sep { color: rgba(244,241,233,.4); }
.site-header--noir .langswitch a.is-current {
  color: var(--on-noir); font-weight: var(--w-semi);
}

.utilities {
  order: 3; display: flex; align-items: center; gap: 18px; color: var(--ink);
}
.site-header--noir .utilities { color: var(--on-noir); }
.utilities a { display: inline-flex; opacity: .9; transition: opacity var(--dur) var(--ease); }
.utilities a:hover { opacity: 1; }

/* Subnav rows — centred under the masthead, same type size as the section
   links, an equal vertical gap between rows. */
.subnav {
  display: flex; align-items: center; justify-content: center;
  gap: 32px; flex-wrap: wrap;
  padding: 8px var(--gutter) 0;
  background: var(--paper);
}
.subnav a {
  font-family: var(--sans); font-weight: var(--w-med);
  font-size: var(--fs-nav); line-height: 1; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-mute); padding-bottom: 2px;
  border-bottom: 1px solid transparent; white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.subnav a:hover { color: var(--ink); }
.subnav a.is-active { color: var(--ink); font-weight: var(--w-semi); }
/* The first subnav row is pulled up to sit midway between the section links
   and the third row; the third row (lighter colour) keeps the same row gap. */
.mainnav + .subnav { padding-top: 0; margin-top: -10px; }
.subnav--third { gap: 28px; padding-top: 20px; }
.subnav--third a { font-size: var(--fs-nav); letter-spacing: 0.18em; color: var(--ink-faint); }
.subnav--third a:hover { color: var(--ink-mute); }
.subnav--third a.is-active { color: var(--ink); font-weight: var(--w-semi); }

/* =====================================================================
   MANIFESTO 1980 — an imaginary widescreen (9:4) frame, scan left + the
   typed list (multi-column) right, keeping the unified master look.
   ===================================================================== */
.manifesto {
  display: flex; justify-content: center;
  padding: 36px var(--gutter) 48px;
}
.manifesto__frame {
  width: 100%; aspect-ratio: 9 / 4; max-height: calc(100vh - 200px);
  display: grid; grid-template-columns: 0.72fr 1.5fr;
  border: 1px solid var(--line); overflow: hidden;
}
.manifesto__scan {
  position: relative; overflow: hidden; background: var(--paper);
  display: flex; align-items: center; justify-content: flex-start;
}
/* show the whole sheet (never crop the list), pulled to the left edge with
   minimal margin so it doesn't float in empty space. */
.manifesto__scan img {
  width: 100%; height: 100%; object-fit: contain; object-position: left center;
  display: block; padding: clamp(8px, 1.6vh, 16px);
}
.manifesto__placeholder { color: var(--ink-faint); }

.manifesto__typed {
  padding: clamp(20px, 3vh, 40px) clamp(20px, 2.5vw, 40px);
  overflow: hidden; display: flex; align-items: center;
}
/* Three balanced columns across the typed area. CSS multi-columns keep each
   column independent, so long phrases wrap inside their own column and never
   collide with or get clipped by the next one, at any width. */
.manifesto__list {
  margin: 0; padding: 0; list-style: none; width: 100%;
  column-count: 3; column-gap: clamp(20px, 3vw, 44px); column-fill: balance;
  font-family: var(--sans); font-weight: var(--w-reg);
  font-size: clamp(9px, 0.9vw, 12px); line-height: 1.65;
  color: var(--ink-soft);
}
.manifesto__list li { break-inside: avoid; }
/* clickable motifs (gold underline grows on hover); empty motifs are quiet. */
.manifesto__list a {
  color: var(--ink-soft); text-decoration: none;
  background-image: linear-gradient(var(--gold-deep), var(--gold-deep));
  background-size: 0% 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size var(--dur) var(--ease), color var(--dur) var(--ease);
}
.manifesto__list a:hover { color: var(--ink); background-size: 100% 1px; }
.manifesto__list a.is-active { color: var(--ink); background-size: 100% 1px; }
.manifesto__empty { color: var(--ink-faint); }
@media (max-width: 720px) {
  .manifesto__frame { aspect-ratio: auto; grid-template-columns: 1fr; max-height: none; }
  .manifesto__scan { aspect-ratio: 4 / 3; border-right: 0; border-bottom: 1px solid var(--line); }
  .manifesto__list { columns: 2; }
}

/* The motif gallery follows the composition and reuses the catalogue feed.
   scroll-margin-top lands it just below the sticky header when the page
   scrolls to it on open (manifesto.html). */
.manifesto-gallery { padding-top: 8px; scroll-margin-top: 130px; }
.manifesto-gallery__title {
  font-family: var(--serif); font-weight: var(--w-reg);
  font-size: var(--fs-h2); line-height: var(--lh-tight);
  letter-spacing: var(--track-tight); color: var(--ink);
  padding: 24px var(--gutter) 0;
}
.manifesto-gallery__empty { padding: 24px var(--gutter); color: var(--ink-mute); }

/* =====================================================================
   CONTACT — the master-slide treatment, true to its proportions: a full
   9:4 framed stage (a 200% stand-in) over a two-column caption carrying the
   atelier details. Stage + caption fit one screen, no scrolling.
   ===================================================================== */
.contact-master {
  display: flex; flex-direction: column; align-items: stretch;
  padding: 28px var(--gutter) 28px; gap: 28px;
}
/* identical stage proportions to .master__stage (9:4, capped to viewport). */
.contact-master__stage {
  position: relative; width: 100%; aspect-ratio: 9 / 4;
  max-height: calc(100vh - 220px);
  border: 1px solid var(--line); overflow: hidden;
  /* image cropped to fill the 9:4 frame (no zoom), centred. */
  background-repeat: no-repeat; background-position: center center;
  background-size: cover;
}

/* two-column caption: note + email + phone (right) | address (left) */
.contact-master__caption {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 24px var(--s-8); align-items: start;
}
.contact__col { margin: 0; }
.contact__col--main { text-align: right; }
.contact__col--address { text-align: left; }
@media (max-width: 720px) {
  .contact-master__caption { grid-template-columns: 1fr; gap: 24px; }
  .contact__col { text-align: center; }
}

/* One uniform line style everywhere (the jewelry-category-nav font: sans,
   tracked caps) — same font and size in both columns, rows aligned. */
.contact__lines {
  margin: 0; font-family: var(--sans); font-weight: var(--w-med);
  font-size: var(--fs-sm); letter-spacing: var(--track-nav); text-transform: uppercase;
  line-height: 2; color: var(--ink-soft);
}
.contact__lines .contact__note { color: var(--ink-mute); }
.contact__lines a {
  color: var(--ink); text-decoration: none; text-transform: none;
  letter-spacing: 0.02em;
  background-image: linear-gradient(var(--gold-deep), var(--gold-deep));
  background-size: 0% 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size var(--dur) var(--ease);
}
.contact__lines a:hover { background-size: 100% 1px; }

/* =====================================================================
   PRESS — a column of master-style slabs, scrolled top to bottom. Each
   article is a framed scan (sized to its own proportions, capped to the
   viewport) or a paper plate carrying the title when there is no image.
   ===================================================================== */
/* Newest → oldest, one entry per row with generous air around each. The column
   is centred and width-capped so wide spreads don't sprawl edge-to-edge, and
   the large gap lets each publication read as its own plate. */
.press {
  display: flex; flex-direction: column; gap: clamp(36px, 5vw, 64px);
  padding: clamp(10px, 1.4vw, 18px) var(--gutter) clamp(96px, 12vw, 160px);
  align-items: center; max-width: 1180px; margin: 0 auto;
}
/* The item shrinks to its image's rendered width (fit-content), so the caption
   below — stretched to the item's width — has its left/right edges flush with
   the image edges. Capped to the column width; centred as a block. */
.press__item {
  display: flex; flex-direction: column; align-items: stretch;
  width: fit-content; max-width: 100%; margin: 0 auto;
}

/* the image's link wrapper: a block that shrinks to the image so the caption
   (a sibling, stretched to the item width) stays flush with the image edges. */
.press__shot { display: block; width: fit-content; max-width: 100%; }

/* image scans: the frame hugs the scan, which keeps its own aspect ratio and
   is capped to a comfortable height so portrait magazine pages aren't tiny. */
.press__img {
  display: block; max-width: 100%; max-height: 72vh; width: auto; height: auto;
  background: var(--paper); border: 1px solid var(--line);
  transition: border-color .2s var(--ease);
}
.press__item:hover .press__img { border-color: var(--line-strong); }

/* paper plate (no image) keeps the wide framed stage with the title. */
.press__stage {
  position: relative; width: 100%; aspect-ratio: 9 / 4;
  max-height: calc(100vh - 220px);
  background: var(--paper); overflow: hidden;
}
.press__stage::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 1px solid var(--line);
}

/* Paper plate (no image) — gallery wall-text: label, big serif title, cue. */
.press__plate {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 22px;
  text-align: center; padding: var(--s-7);
}
.press__label { color: var(--ink-faint); }
.press__title {
  margin: 0; font-family: var(--serif); font-weight: var(--w-reg);
  font-size: clamp(1.75rem, 4vw, 3rem); line-height: var(--lh-tight);
  letter-spacing: var(--track-tight); color: var(--ink);
  max-width: 22ch;
}
.press__item:hover .press__stage::after { border-color: var(--line-strong); }

/* caption beneath an article — publication name (Bodoni Antiqua small caps) +
   year tag on the left; the action cues (PDF / Read online) at the right edge.
   The gap between the cover and this row matches the jewelry overview cell's
   image→name gap (14px). */
.press__caption {
  margin-top: 14px; width: 100%;
  display: flex; align-items: baseline; justify-content: space-between; gap: 24px;
}
.press__title-group { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
/* Name + year match the jewelry grid cell exactly (.cell__name / .cell__year):
   fixed 18px small caps + 11px sans year, so the press list reads at the same
   scale as the jewelry overview it sits beside. */
.press__name {
  margin: 0; font-family: var(--serif-sc); font-weight: var(--w-reg);
  font-size: 18px; line-height: 1.1; letter-spacing: 0.01em; color: var(--ink);
}
.press__sub {
  font-family: var(--sans); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* cues: one or two independent links (PDF / Read online), each darkening on its
   own hover. Stacked vertically and right-aligned — "PDF" stays at the top-right
   (its single-cue position), "Read online" sits beneath it, also right-aligned. */
.press__cues {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: 8px; white-space: nowrap; flex: none;
}
.press__cue { color: var(--ink-mute); text-decoration: none; transition: color var(--dur) var(--ease); }
.press__cue:hover { color: var(--ink); }

/* =====================================================================
   SEARCH — the catalogue search. Field front-and-centre; results render
   below in the same gallery feed as the categories.
   ===================================================================== */
.search {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 64px var(--gutter) 8px;
}
/* Empty state: lift the field into the centre of the viewport. */
.search--empty {
  justify-content: center;
  min-height: calc(100vh - 180px); padding-bottom: 64px;
}
.search__form { width: 100%; max-width: 680px; }
.search__field {
  display: flex; align-items: center; gap: 14px;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 12px;
}
.search__glyph { color: var(--ink-mute); flex: none; }
.search__input {
  flex: 1; border: none; outline: none; background: transparent;
  font-family: var(--serif); font-weight: var(--w-reg);
  font-size: clamp(1.5rem, 3.5vw, 2.25rem); line-height: 1.1;
  color: var(--ink); padding: 0; min-width: 0;
}
.search__input::placeholder { color: var(--ink-faint); }
.search__exit {
  flex: none; display: inline-flex; align-items: center;
  color: var(--ink-mute); padding: 6px 2px; line-height: 0;
  transition: color var(--dur) var(--ease);
}
.search__exit:hover { color: var(--ink); }
.search__submit {
  flex: none; border: none; background: none; cursor: pointer;
  color: var(--ink-mute); padding: 6px 2px;
  transition: color var(--dur) var(--ease);
}
.search__submit:hover { color: var(--ink); }
.search__count {
  margin-top: 28px; color: var(--ink-mute);
}
.search__count .search__for { color: var(--ink-faint); }

/* =====================================================================
   LANDING — "The Plate": full-bleed noir hero, one featured piece.
   ===================================================================== */
.plate { position: relative; width: 100%; height: 100vh; min-height: 640px;
  background: #000; overflow: hidden; }
/* iOS Safari counts its retractable toolbars into 100vh, so a bottom-pinned hero
   hides under the browser bar. Use the dynamic viewport height where supported so
   the image's bottom edge stays visible; 100vh above is the fallback. */
@supports (height: 100dvh) { .plate { height: 100dvh; } }
/* Full-width hero centred on the subject: the image spans the full width; for a
   tall (portrait) source the extra height is cropped evenly top & bottom with the
   focal point (the earrings, ~43% down) held at the viewport centre. The space
   that isn't covered falls back to the plate's black background. */
.plate__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 36%;
}
/* Editorial poster hero (HomePage.hero_image): fills the viewport (cover); the
   object-position keeps its baked-in text block in frame across aspect ratios.
   Portrait screens get the portrait version (<picture>, max-aspect-ratio 5/6). */
.plate--poster .plate__img { object-position: 52% 45%; }
@media (max-aspect-ratio: 5/6) { .plate--poster .plate__img { object-position: 44% 49%; } }
.plate--light { background: #ecebe7; }   /* the poster's paper tone, behind the image */
.plate__caption {
  position: absolute; left: var(--gutter); bottom: 72px; z-index: 2;
  max-width: 760px; display: block; text-align: left;
}
.plate__caption-row { display: flex; align-items: baseline; gap: 20px; }
.plate__name {
  font-family: var(--serif-sc); font-weight: var(--w-reg);
  font-size: clamp(30.8px, 4.2vw, 51.8px); line-height: 0.98; letter-spacing: 0.005em;
  color: var(--on-noir); padding-bottom: 4px;
  border-bottom: 1px solid transparent; transition: border-color .25s var(--ease);
}
@media (max-width: 720px) { .plate__name { font-size: clamp(44px, 6vw, 74px); } }
.plate__caption:hover .plate__name { border-bottom-color: var(--gold-light); }
.plate__year {
  font-family: var(--sans); font-weight: var(--w-med); font-size: 12px;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: rgba(244,241,233,.5); font-variant-numeric: tabular-nums;
}

/* =====================================================================
   FEED — the Overview and per-category catalogues.
   A 2-up grid of wide preview frames; the open piece takes its own
   full-width "master" slot spanning both columns.
   ===================================================================== */
.feed {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 44px 24px; padding: 18px var(--gutter) 64px;
  /* feed.js manages scroll position itself when a master opens; the browser's
     own scroll-anchoring would fight that and cause unpredictable jumps. */
  overflow-anchor: none;
}
@media (max-width: 560px) { .feed { grid-template-columns: 1fr; } }

/* The open master spans the full feed width. */
.feed__master { grid-column: 1 / -1; }
/* `hidden` must beat the cell's display:flex (the open piece's preview cell). */
.cell[hidden] { display: none; }

/* --- a collapsed preview cell --- */
.cell {
  border: none; background: none; padding: 0; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 14px; width: 100%;
}
/* Jewelry preview frame — LOCKED to the exact 9:4 (2250:1000) crop the images
   are prepared at. The ratio must never change (no responsive override), and
   the image fills the frame edge-to-edge (object-fit:cover, no padding) so the
   carefully-chosen fragment is shown pixel-exact. Because the source images are
   themselves 9:4, `cover` displays 100% of them with no cropping. */
.cell__frame {
  position: relative; width: 100%; aspect-ratio: 9 / 4; overflow: hidden;
  background: var(--paper);
}
/* Hairline frame as an overlay above the image so the contour stays unbroken
   where the photo reaches the edge. */
.cell__frame::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 1px solid var(--line); transition: border-color .2s var(--ease);
}
.cell__frame--noir { background: var(--noir); }
.cell:hover .cell__frame::after { border-color: var(--ink); }
.cell__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}
.cell__meta {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.cell__name { font-family: var(--serif-sc); font-size: 18px; letter-spacing: 0.01em; color: var(--ink); }
.cell__year {
  font-family: var(--sans); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* =====================================================================
   MASTER — the expanded piece: a 9:4 stage spanning the feed width, then
   name + year left and Enquire right on one caption line.
   ===================================================================== */
/* The stage is LOCKED to the exact 9:4 (2250:1000) crop at every viewport:
   no max-height cap, no responsive override. The image fills the frame
   edge-to-edge (cover); since the source is 9:4, all of it shows. */
.master__stage {
  position: relative; width: 100%; aspect-ratio: 9 / 4;
  background: var(--paper); overflow: hidden;
  /* Vertical pans stay native (page scroll, the scroll slide); horizontal
     swipes reach feed.js uncontested, on Android as well as iOS. */
  touch-action: pan-y pinch-zoom;
}
/* Multi-image pieces: clicking the stage advances to the next image (matches the
   biography galleries), so hint it with a pointer. */
.master__stage--clickable { cursor: pointer; }
/* Hairline frame drawn as an overlay ABOVE the image, so the contour stays
   unbroken even where the photo reaches the edge of the stage. Sits below the
   close/pager controls (z-index 2). */
.master__stage::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 1px solid var(--line);
}
.master__stage--noir { background: var(--noir); }
.master__shot {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  opacity: 0; transition: opacity .5s cubic-bezier(.4,0,.1,1);
  /* Non-current slides are transparent but still stacked on top in DOM order;
     without this they'd intercept wheel/drag/click meant for the current slide.
     This matters for the scroll slide, whose wheel must reach the window itself
     (an image/video slide is unaffected — clicking anywhere still advances). */
  pointer-events: none;
}
.master__shot.is-current { opacity: 1; pointer-events: auto; }
/* A video slide: a self-hosted clip in a native <video> that feed.js injects
   the first time the slide is shown. Letterboxed on the slide's own backdrop
   (the clips are not all 9:4). No controls; clicks pass through to the stage so
   a video slide advances like an image (no trap). */
.master__shot--video video {
  display: block; position: absolute; top: 0; left: 0; inset: 0;
  width: 100%; height: 100%; max-width: 100%; max-height: 100%;
  object-fit: contain; object-position: center;
  pointer-events: none;
}

/* A tall scroll slide: the shot IS a vertical scroll window. The pre-cropped
   image already ends at its bottom framing (Magdalena: the tassel tip pinned at
   the chorinea point; Selvans IV: the current main crop), so scrolling bottoms
   out there and reveals more above. feed.js pins it to the bottom when the slide
   becomes current and captures the wheel/drag.
   Image width is --scroll-w of the stage: 100% for frame-width assets (a 2250-
   wide composed crop), or a smaller value per image when the raw photo must
   render at true master scale (Magdalena's necklace = 86%). */
.master__shot--scroll {
  background: var(--paper);
  overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  --scroll-w: 100%;             /* set inline per image (JewelryImage.scroll_width) */
  scrollbar-width: thin; scrollbar-color: rgba(0,0,0,.35) transparent;
}
.master__stage--noir .master__shot--scroll {
  background: var(--noir); scrollbar-color: rgba(255,255,255,.4) transparent;
}
.master__shot--scroll img {
  display: block; width: var(--scroll-w); margin: 0 auto;
  height: auto; object-fit: initial;   /* override the .master__shot cover rules */
}
.master__shot--scroll::-webkit-scrollbar { width: 9px; }
.master__shot--scroll::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.28); border-radius: 5px;
}
.master__shot--scroll::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,.45); }
/* On a dark (noir) stage a dark thumb is invisible — use a light thumb instead. */
.master__stage--noir .master__shot--scroll::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.35);
}
.master__stage--noir .master__shot--scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(255,255,255,.55);
}

/* Up-arrow discovery hint for a scroll slide: they open at the bottom and reveal
   more above, but read as a static image otherwise (no persistent scrollbar on
   touch). A small round arrow chip at the RIGHT edge, vertically centred (where
   the scrollbar sits on desktop). A stage-level sibling of the scroll window so
   it doesn't scroll with the image. Shown only while a scroll slide is current
   (feed.js adds .has-scroll-current) and faded out once the viewer scrolls
   (feed.js adds .hint-dismissed). Reads on light and dark/textured backdrops. */
.master__scroll-hint {
  position: absolute; right: 14px; top: 50%; z-index: 2;
  display: none; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  color: #fff; background: rgba(20,20,20,.55);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  pointer-events: none; user-select: none;
  transition: opacity .5s ease; opacity: 1;
  transform: translateY(-50%);
}
/* The arrow is a marker, not a control (clicking anywhere on the image scrolls
   up); it just needs to show while a scroll slide is current and fade on scroll. */
.master__stage.has-scroll-current .master__scroll-hint { display: inline-flex; }
.master__stage.hint-dismissed .master__scroll-hint { opacity: 0; }
.master__scroll-hint-arrow {
  font-size: 16px; line-height: 1;
  animation: hintbob 1.7s ease-in-out infinite;
}
@keyframes hintbob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) {
  .master__scroll-hint-arrow { animation: none; }
}

.master__close {
  position: absolute; top: 16px; right: 18px; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; padding: 0;
  border: none; cursor: pointer; line-height: 1; font-size: 16px;
  /* A dark disc behind the ✕ (like .master__scroll-hint) so it stays legible
     over any slide — including a light-backed scroll image on a noir stage,
     where a bare light glyph would vanish against the pale photo. */
  color: #fff; background: rgba(20,20,20,.55);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}

/* Image navigation overlays the image, in its lower-right corner. */
.master__pager {
  position: absolute; right: 18px; bottom: 16px; z-index: 2;
  display: flex; align-items: center; gap: 16px; color: var(--ink-soft);
}
.master__stage--noir .master__pager { color: var(--on-noir); }
.master__pager button {
  border: none; background: none; cursor: pointer; padding: 2px 4px;
  font-family: var(--serif); font-size: 18px; line-height: 1; color: inherit;
}
.master__count {
  font-family: var(--sans); font-size: 11px; letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
}
.master__count .sep { opacity: .5; margin: 0 5px; }

.master__caption { margin-top: 28px; }
.master__caption-row {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
}
.master__title-group { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; }
.master__name {
  margin: 0; font-family: var(--serif-sc); font-weight: var(--w-reg);
  font-size: clamp(34px, 4vw, 52px); line-height: 1.0; letter-spacing: 0.01em;
  color: var(--ink);
}
.master__sub {
  font-family: var(--sans); font-size: 12px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.master__enquire {
  font-family: var(--sans); font-weight: var(--w-med); font-size: 11px;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--on-noir);
  background: var(--ink); padding: 14px 30px; border-radius: var(--r-sm);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) var(--ease);
}
.master__enquire:hover { background: var(--ink-soft); }
.master__desc {
  margin: 14px 0 0; font-family: var(--serif); font-weight: var(--w-reg);
  font-size: 20.8px; line-height: 1.62; color: var(--ink-soft);
  text-wrap: pretty; max-width: 760px;
}

/* =====================================================================
   BIOGRAPHY — editorial column with interleaved 9:4 widescreen figures.
   Prose lives in a centred, readable measure; figures break out wider so
   the images dominate, in Otto's preferred widescreen format.
   ===================================================================== */
/* No page title — the masthead subnav already reads "Biography". The lede
   opens the page directly, with a little breathing room below the subnav. */
.bio { padding: clamp(28px, 6vh, 64px) var(--gutter) 96px; }

/* Readable prose measure, centred. */
.bio__col { max-width: 640px; margin: 0 auto; }
.bio__col p {
  /* Match the jewelry master slide's description body (.master__desc): 20.8px. */
  font-family: var(--serif); font-size: 20.8px;
  line-height: var(--lh-body); color: var(--ink-soft); margin: 0 0 1.15em;
}
.bio__col p:last-child { margin-bottom: 0; }
.bio__col em { font-style: italic; }

/* Opening: portrait beside the large first sentence, the rest of the lede
   flowing beneath the sentence (portrait spans both). */
.bio-open {
  max-width: 1320px; margin: 0 auto clamp(8px, 3vh, 28px);
  display: grid; grid-template-columns: 1.15fr 1fr;
  gap: clamp(28px, 4vw, 64px); align-items: start;
}
.bio-open__portrait { margin: 0; }
.bio-open__portrait img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--line);
}
/* The opening sentence sits beside the portrait, aligned to its bottom edge. */
.bio-open__text { align-self: end; }
.bio-open__lead {
  margin: 0; font-family: var(--serif); font-weight: var(--w-reg);
  font-size: clamp(18px, 2.1vw, 28px); line-height: 1.16;
  letter-spacing: -0.012em; color: var(--ink);
}

@media (max-width: 760px) {
  .bio-open { grid-template-columns: 1fr; gap: 22px; }
  .bio-open__portrait { max-width: 320px; }
}

/* Figures break out to a wide measure and breathe vertically. */
.bio-fig {
  max-width: 1180px; margin: clamp(48px, 7vh, 96px) auto;
}
.bio-fig__stage {
  position: relative; width: 100%; aspect-ratio: 9 / 4;
  max-height: calc(100vh - 200px);
  background: var(--paper); overflow: hidden;
  touch-action: pan-y pinch-zoom;
}
/* Hairline frame as an overlay above the image (matches .master__stage). */
.bio-fig__stage::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 1px solid var(--line);
}
.bio-fig--gallery .bio-fig__stage { cursor: pointer; }
.bio-fig__shot {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* contain (not cover): biography images are shown in full, never cropped. The
     current images are all 9:4 like the stage, so this fits exactly; a differently
     shaped image letterboxes against the paper backdrop rather than losing edges. */
  object-fit: contain;
  opacity: 0; transition: opacity .5s cubic-bezier(.4,0,.1,1);
}
.bio-fig__shot.is-current { opacity: 1; }

/* Pager — lower-right of the frame, like the master pager. */
.bio-fig__pager {
  position: absolute; right: 18px; bottom: 16px; z-index: 2;
  display: flex; align-items: center; gap: 16px; color: var(--on-noir);
  mix-blend-mode: difference;
}
.bio-fig__pager button {
  border: none; background: none; cursor: pointer; padding: 2px 4px;
  font-family: var(--serif); font-size: 18px; line-height: 1; color: inherit;
}
.bio-fig__count {
  font-family: var(--sans); font-size: 11px; letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
}
.bio-fig__count .sep { opacity: .5; margin: 0 5px; }

.bio-fig__caption {
  margin-top: 14px; font-family: var(--sans); font-size: 12px;
  letter-spacing: 0.04em; color: var(--ink-mute); line-height: 1.5;
}


/* =====================================================================
   COMPACT HEADER (<=1149px) — a compact top bar with a hamburger that opens a
   full-screen menu overlay. Top bar:  [≡] EN/DE  ——  otto jakob  ——  🔍 ⧉
   Open: the whole header becomes a full-screen overlay showing the section
   links (column 1), plus the category subcategories (column 2) and necklace
   sub-subcategories (column 3) when present — as in the reference.

   The switch happens at 1149px (not 720px) because that is where the one-line
   desktop header stops fitting: the enlarged wordmark + the six section links
   (widest in German) + the EN/DE + icons need ~1108px on one line, so below
   ~1150px we fold the nav into the hamburger rather than cramp or overlap it.
   (Only the HEADER folds here; the page grid/hero keep their own 720px mobile
   breakpoints — a laptop at 1000px gets the hamburger but the desktop grid.)
   ===================================================================== */
@media (max-width: 1149px) {
  /* The header itself is not sticky here; the TOP BAR is fixed (below) so the
     hamburger stays reachable while the menu and page scroll under it. */
  .site-header { position: static; }

  /* -- Top bar: fixed at the top, always visible -- */
  .masthead {
    /* One-line top bar. Left group (hamburger + EN/DE) and right group (icons)
       flow inline; the wordmark is absolutely centred over the bar so it stays
       in the true middle regardless of the side groups' widths. */
    position: fixed; top: 0; left: 0; right: 0; z-index: 50;
    display: flex; align-items: center; gap: 12px;
    padding: 14px var(--gutter); min-height: 52px;
    background: var(--paper);
  }
  .site-header--noir .masthead,
  .site-header--overlay .masthead { background: transparent; }
  /* The page content clears the fixed bar via body padding — except on the
     landing, where the bar deliberately overlays the hero. */
  body { padding-top: 52px; }
  body:has(.site-header--noir),
  body:has(.site-header--overlay) { padding-top: 0; }
  .navtoggle {
    order: 0;
    display: inline-flex; align-items: center;
    background: none; border: none; padding: 0; cursor: pointer;
  }
  .navtoggle__bars { display: inline-block; width: 22px; height: 13px; position: relative; }
  .navtoggle__bars span {
    position: absolute; left: 0; width: 100%; height: 1.6px; background: currentColor;
    transition: transform .25s var(--ease), opacity .2s var(--ease);
  }
  .navtoggle__bars span:nth-child(1) { top: 0; }
  .navtoggle__bars span:nth-child(2) { top: 6px; }
  .navtoggle__bars span:nth-child(3) { top: 12px; }
  .navtoggle { color: var(--ink); }
  .site-header--noir .navtoggle { color: var(--on-noir); }

  /* EN/DE — inline, just right of the hamburger. The active language is marked
     by BOLD only (no underline), so the glyphs centre cleanly with the hamburger
     bars, wordmark and icons (a hair of downward nudge lands them on the bar). */
  .langswitch { order: 1; margin: 0; align-items: center; position: relative; top: 1px; }
  .langswitch a { padding-bottom: 0; }
  .langswitch a.is-current { font-weight: var(--w-semi); }

  /* Icons — pushed to the far right of the bar. */
  .utilities { order: 2; margin-left: auto; }

  /* Wordmark — absolutely centred over the bar (true middle of the viewport),
     a little smaller than on desktop. */
  .wordmark {
    order: 1; position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
  }
  .wordmark__mark { height: 21px; width: calc(21px * 56.69 / 14.17); }

  /* -- The nav: CLOSED by default (hidden). It stays closed across page loads
     and navigation until the user taps the hamburger, which adds `.is-open`. -- */
  .mainnav { display: none; }
  .subnav  { display: none; }

  /* Open (only when `.is-open`): the menu is a grid of columns below the fixed
     top bar. Layout differs by page type:
       • Non-noir (gallery/list pages): the menu sits IN FLOW (static), so it
         pushes the page content down — the first piece stays visible below it.
       • Noir landing (home): the menu OVERLAYS the hero (absolute, anchored at
         the top) and scrolls away with the document, leaving the art unbroken. */
  .site-header.is-open {
    display: grid;
    grid-template-columns: auto auto auto;
    grid-auto-rows: min-content;
    column-gap: 16px; align-content: start;
    /* Non-noir menu is in flow; body's 52px top padding already clears the fixed
       bar, so the menu's own top padding is just breathing room (20px). */
    padding: 20px var(--gutter) var(--gutter);
    background: var(--paper);
  }
  .site-header--noir.is-open {
    position: absolute; top: 52px; left: 0; right: 0; z-index: 45;
    background: var(--noir);
  }
  /* Light landing hero: the same overlaying menu, on paper, with the default
     ink tones; the fixed bar turns paper too so the two read as one sheet. */
  .site-header--overlay.is-open {
    position: absolute; top: 52px; left: 0; right: 0; z-index: 45;
    background: var(--paper);
  }
  .site-header--overlay.is-open .masthead { background: var(--paper); }

  /* Turn the hamburger into an X when open. */
  .site-header.is-open .navtoggle__bars span:nth-child(1) { top: 6px; transform: rotate(45deg); }
  .site-header.is-open .navtoggle__bars span:nth-child(2) { opacity: 0; }
  .site-header.is-open .navtoggle__bars span:nth-child(3) { top: 6px; transform: rotate(-45deg); }

  /* .mainnav is absolutely placed on desktop; here it flows into column 1. */
  .site-header.is-open .mainnav { position: static; grid-row: 1; grid-column: 1; }
  .site-header.is-open .subnav { grid-row: 1; grid-column: 2; }
  .site-header.is-open .subnav--third { grid-row: 1; grid-column: 3; }

  /* All three columns: identical type size, line-height and row gap so the
     entries align line-to-line, and every column's first line sits at the same
     height (all start on grid row 2 with the same margin-top / padding). */
  .site-header.is-open .mainnav,
  .site-header.is-open .subnav,
  .site-header.is-open .nav-sections {
    display: flex; flex-direction: column; flex-wrap: nowrap;
    align-items: flex-start; justify-content: flex-start; align-content: flex-start;
    gap: 12px; margin-top: 22px; padding: 0; background: none;
  }
  .site-header.is-open .nav-sections { margin-top: 0; }   /* nav-sections is inside .mainnav */

  /* All menu entries share one font size AND line-height so every row aligns
     across the three columns. Only the long compound label ("Manschettenknöpfe")
     may wrap — at its soft-hyphen break, never mid-word — so all three columns
     fit the phone width without horizontal scroll; the smaller font keeps every
     other single-word label on one line. Its own wrapped line gets a touch more
     leading via padding so its two lines don't touch, without changing row rhythm. */
  .site-header.is-open .nav-sections a,
  .site-header.is-open .subnav a {
    font-size: 12.5px; letter-spacing: 0.06em; line-height: 1;
    white-space: nowrap;
  }
  .site-header.is-open .subnav a { white-space: normal; }

  /* Lighter with each layer: sections darkest, subcategories mid, sub-sub
     lightest. Active items are bold (and one step darker) for emphasis. */
  .site-header.is-open .nav-sections a       { color: var(--ink-soft); }
  .site-header.is-open .nav-sections a.is-active { color: var(--ink); font-weight: var(--w-semi); }
  .site-header.is-open .subnav a             { color: var(--ink-mute); }
  .site-header.is-open .subnav a.is-active   { color: var(--ink-soft); font-weight: var(--w-semi); }
  .site-header.is-open .subnav--third a      { color: var(--ink-faint); }
  .site-header.is-open .subnav--third a.is-active { color: var(--ink-mute); font-weight: var(--w-semi); }

  /* On the noir landing the menu overlays a black hero, so the dark ink tones
     above vanish. Use the same warm light palette as the wordmark/utilities,
     fading one step per layer. */
  .site-header--noir.is-open .nav-sections a            { color: var(--on-noir); }
  .site-header--noir.is-open .nav-sections a.is-active  { color: var(--gold-light); font-weight: var(--w-semi); }
  .site-header--noir.is-open .subnav a                  { color: rgba(244,241,233,.72); }
  .site-header--noir.is-open .subnav a.is-active        { color: var(--on-noir); font-weight: var(--w-semi); }
  .site-header--noir.is-open .subnav--third a           { color: rgba(244,241,233,.5); }
  .site-header--noir.is-open .subnav--third a.is-active { color: rgba(244,241,233,.72); font-weight: var(--w-semi); }

}

/* =====================================================================
   PROSE PAGES (imprint, privacy) — a centred readable column, typography
   matching the biography text; the body is editor HTML from the admin.
   ===================================================================== */
.prose { max-width: 640px; margin: 0 auto; padding: clamp(28px, 6vh, 64px) var(--gutter) 96px; }
.prose__title {
  font-family: var(--serif); font-weight: var(--w-reg);
  font-size: var(--fs-h2); line-height: var(--lh-tight);
  letter-spacing: var(--track-tight); color: var(--ink); margin: 0 0 32px;
}
.prose__body { font-family: var(--serif); font-size: 18px; line-height: var(--lh-body); color: var(--ink-soft); }
.prose__body p { margin: 0 0 1em; }
.prose__body h2 { font-family: var(--serif); font-weight: var(--w-reg); font-size: 22px; color: var(--ink); margin: 1.6em 0 .5em; }
.prose__body a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--gold-deep); }
/* Impressum + Datenschutz share one page: the second title starts a new block;
   anchors clear the sticky header; lists and sub-headings in the editor HTML. */
.prose__body h3 { font-family: var(--serif); font-weight: var(--w-semi); font-size: 18px; color: var(--ink); margin: 1.4em 0 .4em; }
.prose__body ul { margin: 0 0 1em; padding-left: 1.2em; }
.prose__body li { margin: 0 0 .3em; }
.prose__jump { font-family: var(--sans); font-size: 13px; letter-spacing: 0.04em; margin: -20px 0 32px; }
.prose__jump a { color: var(--ink-mute); text-decoration: none; }
.prose__jump a:hover { color: var(--ink); }
.prose__copyright { font-family: var(--serif); font-size: 16px; color: var(--ink-mute); margin: 2em 0 0; }
.prose__title--second { margin-top: 96px; padding-top: 48px; border-top: 1px solid var(--line); }
.prose [id] { scroll-margin-top: 110px; }
