/* Siska Katrine Jørgensen — mobile-first, gallery white.
   Written narrow-first: every rule below is the phone layout; min-width
   queries add the wider compositions on top. */

/* Open Sans, the original typeface. Self-hosted rather than loaded from
   Google: it is one less third-party request, and hotlinking Google Fonts
   has been found to breach the GDPR in the EU. One variable file covers
   300-800; unicode-range means latin-ext is only fetched if a page needs it. */
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('../fonts/open-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('../fonts/open-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

*, *::before, *::after { box-sizing: border-box; }

:root {
  color-scheme: light;
  --ink:        #1a1a1a;
  --ink-muted:  #5d5d5d;   /* 6.4:1 on white */
  --rule:       #e4e4e4;
  --paper:      #ffffff;
  --focus:      #2b6cb0;

  /* Menu. #767676 is the lightest grey that still meets AA at 14px (4.54:1) —
     anything lighter fails — so the selected item cannot be lightened further.
     The separation comes from darkening the others instead: 2.99:1 between the
     two, against 1.96:1 for the original's pairing. */
  --nav:         #2e2e2e;   /* 13.4:1 on white */
  --nav-current: #767676;   /*  4.54:1 — the AA floor */
  --body-grey:   #666666;   /* the original's body text, 5.7:1 */

  --gutter:     clamp(1rem, 5.5vw, 3rem);
  --stack:      clamp(2.5rem, 9vw, 5.5rem);  /* space between works */
  --measure:    38rem;                       /* readable line length */
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Open Sans', Arial, Helvetica, sans-serif;
  font-size: 1rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

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

/* Nothing anywhere on the site changes appearance on hover — no underline, no
   colour shift. The pointer cursor is the only cue. Keyboard focus rings are a
   separate thing and stay: they are how someone navigating without a mouse can
   see where they are. */
a { color: inherit; text-decoration: none; }

/* Nor on a tap. iOS otherwise lays a translucent grey box over whatever was
   touched — on a work card, the whole photograph. Set on every element rather
   than left to inheritance, so the buttons and the lightbox backdrop (clickable
   through script) cannot pick up a default of their own. */
* { -webkit-tap-highlight-color: transparent; }

:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

/* The picture viewer and the reader move focus themselves — to the close
   button on opening, back to the picture or page on closing — and the
   browser draws the ring there even after a click, and always after Esc.
   So from a click or a tap until the next Tab, none is drawn (site.js sets
   the class). Moving about with Tab shows them exactly as before. */
.by-pointer :focus-visible { outline: none; }

h1, h2, h3 { font-weight: 600; line-height: 1.25; margin: 0; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--ink); color: #fff; padding: 0.75rem 1rem;
}
.skip:focus { left: 0; }

.muted, .credit { color: var(--ink-muted); }

/* ---------- header ---------- */

.site-head {
  padding: 1rem var(--gutter);
  padding-top: max(1rem, env(safe-area-inset-top));
}
.site-head ul {
  display: flex;
  /* one gap for every item, the bullet included — 22px, as in the original */
  gap: 22px;
  list-style: none;
  margin: 0; padding: 0;
}
.site-head a {
  display: inline-flex; align-items: center;
  min-height: 44px;
  font-size: 0.875rem;
  color: var(--nav);
}
/* The page you are on is the lighter one, as in the original: it recedes
   because you are already there, and the places you can still go stay darker. */
.site-head a[aria-current="page"] { color: var(--nav-current); }

/* The bullet glyph is only about 5px wide, which is far too small to tap.
   Widen the hit area with an overlay so the target reaches ~25x44 without
   changing the spacing by a single pixel. */
.site-head .mark { position: relative; }
.site-head .mark::after { content: ""; position: absolute; inset: 0 -10px; }

/* The menu sits on top of the content below the sidebar width, and with only
   the header's own 1rem under it the first picture came right up against the
   menu — no more space below it than above it. The extra 1.5rem sets it clear. */
main {
  max-width: 74rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-top: 1.5rem;
  padding-bottom: var(--stack);
}

/* ---------- works index ---------- */

.works { list-style: none; margin: 0; padding: 0; }

/* Below the sidebar width each caption sits 0.9rem under its picture, so the
   gap to the next work has to be several times that or the caption floats
   halfway between two pictures and could belong to either. --stack alone
   bottoms out at 2.5rem on a phone, which was that; 5rem keeps the caption
   plainly with the picture above. The desktop sets its own 130px. */
.work-card + .work-card { margin-top: max(5rem, var(--stack)); }
.work-card a { display: block; }

/* Caption: three consecutive lines in one grey. What separates the title is
   weight, not colour or size — that is what makes the original subtle. Set at
   14px on a phone and at the original's 13px from the sidebar width up. */
.work-card__meta { margin-top: 0.9rem; }
.work-card__meta h2,
.work-card__meta .credit {
  margin: 0;
  font-size: 0.875rem;
  color: var(--body-grey);
  line-height: 1.4;
}
.work-card__meta h2     { font-weight: 700; }
.work-card__meta .credit { font-weight: 500; }

/* ---------- work detail ---------- */

/* Vertical rhythm measured off the original: 14px after the title, materials
   and credit as consecutive lines with no gap between them, 14px before the
   description, and 50px before the first image. */
.work__head { margin-block: 0.5rem 14px; max-width: var(--measure); }
.work__head h1 { font-size: clamp(1.25rem, 4.5vw, 1.75rem); }
.work__head .materials,
.work__head .credit { font-size: 0.9375rem; color: var(--ink-muted); line-height: 1.45; }
.work__head .materials { margin: 14px 0 0; }
.work__head .credit    { margin: 0; }

.prose { max-width: var(--measure); margin-bottom: 0; }
.prose p { margin: 0 0 1.15em; }
.prose p:last-child { margin-bottom: 0; }

/* 50px before the first image. Put on the gallery rather than under the
   description so the spacing holds for a work that has no description — the
   margins then collapse to this 50px instead of the head's 14px. */
.gallery { margin-top: 50px; }
.gallery figure { margin: 0; }
/* The same 50px between pictures, so the gallery keeps one rhythm from the
   text down. On a phone each picture fills the width, and with much less than
   this they close up into one continuous strip — which is what made a work
   feel cramped. The desktop steps up to the original's 90px, further down. */
.gallery figure + figure { margin-top: 50px; }

/* Text under a picture, set the way a newspaper sets a caption: smaller and
   greyer than the description, and close under its picture — the same 0.9rem
   the Works page leaves under each photograph — so the 50px that follows
   leaves no doubt which picture it belongs to. */
.gallery figcaption {
  margin-top: 0.9rem;
  max-width: var(--measure);
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--ink-muted);
}
.gallery figcaption p { margin: 0; }
.gallery figcaption p + p { margin-top: 0.6em; }

.zoom {
  display: block; width: 100%;
  padding: 0; border: 0; background: none;
  cursor: pointer;
  font: inherit; color: inherit;
}

/* A video keeps its own shape and is never taller than the screen: a portrait
   one at the column's width would run to 1450px. The width is worked out from
   that height limit as well (--w and --h come from the markup), so the
   controls span the picture rather than an empty box around it. Centred, as
   the one on Brick was on the original site. */
.gallery video {
  display: block;
  width: min(100%, 85vh * var(--w) / var(--h));
  width: min(100%, 85svh * var(--w) / var(--h));
  height: auto;
  margin-inline: auto;
}

/* A publication's pages in rows, as at the end of Konturen on the original:
   three across on a phone, four from a tablet up. Each page gets a hairline
   edge, or white paper disappears into the white page around it. */
.publication__pages {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem 0.75rem;
}
.publication__pages a { display: block; }
.publication__pages img { width: 100%; box-shadow: 0 0 0 1px #d4d4d4; }

/* Previous, All works and Next on one line, a word or two each, so the three
   fit side by side on the narrowest phone. Each is pinned to its own column:
   the first work has no Previous and the last has no Next, and All works has
   to stay in the middle either way. */
.work-nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.75rem;
  margin-top: var(--stack);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9375rem;
}
.work-nav a { min-height: 44px; display: flex; align-items: center; color: var(--ink-muted); }
.work-nav .prev { grid-column: 1; }
.work-nav .all  { grid-column: 2; }
.work-nav .next { grid-column: 3; justify-content: flex-end; }

/* ---------- CV ---------- */

/* On a phone everything runs down one column, so spacing alone has to say
   where one part ends: a clear 1rem between the name and the line about her,
   and 5rem after that and between sections — two and a half times the gap
   between entries, so a new heading reads as a new part, not one more entry.
   At 3.5rem, Education ran straight on into Upcoming exhibitions. */
.cv { max-width: 54rem; }
.cv__head { margin-bottom: 5rem; }
.cv__head h1 { font-size: clamp(1.25rem, 4.5vw, 1.75rem); }
.cv__head .bio { margin: 1rem 0 0; color: var(--ink-muted); }

.cv__section + .cv__section { margin-top: 5rem; }
.cv__section h2 {
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 1rem;
}
.cv dl { margin: 0; }

/* On a phone the year sits above its entry, so a wrapped entry is several
   lines 24.8px apart. The gap between entries has to be clearly larger than
   that or neighbouring entries read as one block — which is what made this
   feel cramped. Sections step up again from there. */
.cv__row + .cv__row { margin-top: 2rem; }
.cv__row dt {
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  font-size: 0.875rem;
}
.cv__row dd { margin: 0.1rem 0 0; }

/* ---------- home / contact ---------- */

/* Contact reads as one plain block, as in the original: the name is set like
   the rest of the text, then the address, then how to reach her. On a phone
   the 1rem drop sets the name clearly further from the menu than the blocks
   below are from each other; the desktop's own drop replaces it.

   On a phone the page is a column as wide as the photo, centred: the photo
   sits in the middle and every line starts at its left edge. A line longer
   than the photo — the email — runs on past its right edge, as far as the
   screen allows, rather than breaking under it. The desktop puts the page
   back in its own column beside the menu. */
.contact {
  --photo: 230px;
  width: var(--photo);
  margin-inline: auto;
  color: var(--body-grey);
  padding-top: 1rem;
}
.contact > h1,
.contact address,
.contact__reach {
  width: max-content;
  /* from the photo's left edge to the right-hand gutter */
  max-width: calc(50vw + var(--photo) / 2 - var(--gutter));
}
.contact h1 { font-size: inherit; font-weight: 400; margin: 0; }

/* The front page is one centred image, 46% of the viewport at every width —
   measured off the original at 375px, 540px, 768px, 1440px and 1920px, where
   it is 46% throughout. It sits about 202px down the page on a phone, which
   already clears the menu — so it takes back main's 1.5rem to stay there. */
.home__image {
  max-width: 46vw;
  margin-inline: auto;
  margin-top: calc(126px - 1.5rem);
}
.home__intro { max-width: var(--measure); color: var(--ink-muted); margin: 1.5rem auto 0; text-align: center; }

/* On a phone every line runs most of the way across the screen, so the blocks
   are held apart by space alone: 2rem after the name and again before the
   email and phone, 4rem before the photo. With the original's 1.3em, 14px and
   45px they closed up into one dense column. The desktop puts those back. */
.contact address { font-style: normal; margin: 2rem 0 0; }
/* the lines are the spans directly inside: a formatted word in a line is a span too */
.contact address > span { display: block; }
/* The email and phone are two separate things to tap, so each gets a 32px
   line rather than the address's 24.8px. The padding stretches each link's
   tap area to fill its own line without moving anything. */
.contact__reach { margin: 2rem 0 0; line-height: 2; }
.contact__reach a { padding-block: 5px; }
/* The studio photo at 230px, its size in the original. Across the full
   width of a phone it took up most of the screen. */
.contact__image { margin-top: 4rem; max-width: var(--photo); }

.notfound { padding-block: var(--stack); }
.notfound p { margin: 0.75rem 0 0; }

/* ---------- lightbox ----------

   Every picture of the work in a row, one screen each, snapping a whole
   picture at a time. Sideways rather than down: a vertical strip hands its
   overshoot at either end to the page underneath on iOS, which a sideways one
   has no axis to do.

   Between the pictures, the 50px that separates them on a phone's page:
   without it a swipe drew one picture's edge straight against the next.
   It shows only mid-swipe; a key or the wheel jumps over it (site.js). */

.lightbox {
  position: fixed; inset: 0; z-index: 50;
  display: flex;
  gap: 50px;
  background: rgba(255, 255, 255, 0.985);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* no swipe-back-a-page when you run off either end */
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.lightbox::-webkit-scrollbar { display: none; }
.lightbox__slide {
  flex: 0 0 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);
  scroll-snap-align: start;
  /* a hard flick still stops at the next picture instead of skipping past it */
  scroll-snap-stop: always;
}
/* min-height: 0 lets the picture give up height to a caption under it;
   object-fit keeps it whole while it does */
.lightbox__slide img { max-width: 100%; max-height: 100%; min-height: 0; flex: 0 1 auto; object-fit: contain; }

/* A picture with a caption keeps clear room under it, so the text never runs
   up against the bottom of the window. */
.lightbox__slide--captioned {
  padding-bottom: calc(env(safe-area-inset-bottom) + clamp(1.75rem, 6vh, 3.5rem));
}

/* The picture's caption, under it as on the page and set the same way.
   site.js makes it exactly as wide as the picture is drawn, so the text
   starts at the picture's left edge and wraps at its right one — kept 1rem
   in from the screen's edges where the picture runs right across it. A long
   one stops at two fifths of the screen and scrolls on its own, and the
   picture is drawn smaller to leave room for it. */
.lightbox__caption {
  flex: none;
  max-width: calc(100% - 2rem);
  max-height: 40%;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin-top: 0.9rem;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--ink-muted);
}
.lightbox__caption p { margin: 0; }
.lightbox__caption p + p { margin-top: 0.6em; }
.lightbox__count {
  position: fixed; top: 0.5rem; left: 1rem;
  display: flex; align-items: center;
  min-height: 44px; margin: 0;
  font-size: 0.8125rem; color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.lightbox__close {
  position: fixed; top: 0.5rem; right: 0.5rem;
  width: 44px; height: 44px;
  border: 0; background: none; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--ink);
}
body.is-locked { overflow: hidden; }

/* ---------- reader ----------

   A publication to read: its pages one under another, opened at the page
   that was clicked. Grey behind white pages so each reads as a sheet; the
   bar keeps the page count and the close button clear of the text. */

.reader {
  position: fixed; inset: 0; z-index: 50;
  background: #ececec;
  /* both ways: zoomed in, a page can be wider than the screen (site.js) */
  overflow: auto;
  overscroll-behavior: contain;
}
.reader:focus { outline: none; }
.reader__bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  padding: max(0.25rem, env(safe-area-inset-top)) 0.5rem 0.25rem 1rem;
  background: rgba(236, 236, 236, 0.94);
}
.reader__count {
  margin: 0;
  font-size: 0.8125rem; color: var(--ink-muted);   /* 5.3:1 on the grey */
  font-variant-numeric: tabular-nums;
}
.reader__close,
.reader__zoom button {
  width: 44px; height: 44px;
  border: 0; background: none; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--ink);
}
/* Zoom out and in, beside the close button. A phone pinches instead, so they
   are there only with a mouse or a trackpad (below). */
.reader__zoom { display: none; margin-left: auto; }
.reader__zoom button[aria-disabled="true"] { color: #b4b4b4; cursor: default; }
.reader__pages {
  display: flex; flex-direction: column; align-items: center;
  gap: 0.75rem;
  padding: calc(56px + env(safe-area-inset-top)) 0.5rem calc(2rem + env(safe-area-inset-bottom));
}
/* zoomed in, the column is as wide as its pages, and never narrower than
   the screen, so a page stays in the middle until it is wider than that */
.reader.is-zoomed .reader__pages { width: max-content; min-width: 100%; }
/* the page's thumbnail stands in, stretched, until PDF.js has drawn it */
.reader__page {
  position: relative;
  /* what is layered inside a page stays under the bar */
  isolation: isolate;
  width: min(100%, 56rem);
  background: #fff center / 100% 100% no-repeat;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.14);
}
.reader__page canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
/* zoomed in, the part on screen drawn sharper, over the whole page (site.js
   sets where) */
.reader__page .reader__detail { right: auto; bottom: auto; z-index: 1; }

/* With a mouse or a trackpad: a page opens whole on the screen however short
   the window, below the bar with a little grey under it, as it does on a
   phone (--ratio is its width over its height, from site.js). From there a
   click zooms in on it, and zoomed in, the pages are dragged about. */
@media (hover: hover) and (pointer: fine) {
  .reader__zoom { display: flex; }
  .reader__page { width: min(100%, 56rem, (100vh - 56px - 1.5rem) * var(--ratio, 1)); cursor: zoom-in; }
  .reader.is-zoomed .reader__page { cursor: grab; }
  .reader.is-dragging,
  .reader.is-dragging .reader__page { cursor: grabbing; }
  .reader__pages { -webkit-user-select: none; user-select: none; }
}

/* ---------- wider screens ---------- */

@media (min-width: 40em) {
  .publication__pages { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2.5rem 1rem; }

  /* Wide enough for the year to sit beside its entry: each row then delimits
     itself and does not need the phone's generous separation. */
  .cv__row { display: grid; grid-template-columns: 7.5rem 1fr; gap: 1rem; }
  .cv__row dt { font-size: 0.9375rem; }
  .cv__row dd { margin-top: 0; }
  .cv__row + .cv__row { margin-top: 0.9rem; }
  .cv__section + .cv__section { margin-top: 3.25rem; }
  .cv__head { margin-bottom: var(--stack); }
  .cv__head .bio { margin-top: 0.4rem; }
}

/* ---------- desktop: the fixed side nav and the layout built around it ----------

   Her original switches at 981px: above it the header is a fixed 222px column
   down the left with the menu stacked vertically; below it the menu sits
   horizontally on top. The left indents on every page (230px on Works, 140px
   on a project, 130px on the CV, 300px on Contact) exist to clear that fixed
   column — which is why they must switch on at exactly the same width as the
   sidebar, and off again below it. */

@media (min-width: 981px) {
  .site-head {
    position: fixed;
    inset: 0 auto 0 0;
    width: 222px;
    padding: 113px 0 0 40px;
    background: var(--paper);
    z-index: 10;
  }
  /* stacked, 33px rows — the bullet is simply the first of them */
  .site-head ul { flex-direction: column; gap: 0; }
  .site-head a { min-width: 142px; min-height: 33px; }

  /* the fixed header is out of flow, so the content sets its own top */
  main { padding-top: 80px; }

  /* Previous / next is a phone convenience — there the menu has scrolled away
     by the time you reach the bottom of a long gallery. On a desktop the menu
     is pinned in the sidebar the whole way down, so this is just noise. */
  .work-nav { display: none; }
  /* that 80px already places the front-page image where the original has it */
  .home__image { margin-top: 0; }

  /* Her original desktop composition, measured off the Divi layout at 1440px
     and 1920px (it was fixed, not fluid): a 960px row holding a 230px indent,
     a 471px image, a 77px gap and a 182px caption. Kept as fr units so the
     proportions survive at any width, and capped at 960px so the images stay
     the size they have always been rather than filling the screen. */
  .works { max-width: 60rem; margin-inline: auto; }

  .work-card a {
    display: grid;
    grid-template-columns: 230fr 471fr 77fr 182fr;
    align-items: start;
  }
  .work-card__img  { grid-column: 2; }
  .work-card__meta { grid-column: 4; margin-top: 0; }
  /* the original's caption size: 13px on an 18.2px line */
  .work-card__meta h2,
  .work-card__meta .credit { font-size: 13px; line-height: 18.2px; }

  /* 130px between works, as in the original */
  .work-card + .work-card { margin-top: 130px; }

  /* Project pages, measured the same way: one 960px row with everything —
     text and images alike — 820px wide and inset 140px from its left edge.
     The inset is the part that had to go on a phone; here there is room. */
  /* The inset lives on the container, not on each child: with border-box that
     keeps the content box exactly 820px and leaves max-width on the children
     free to mean what it says. */
  .work {
    max-width: 60rem;
    margin-inline: auto;
    padding-left: 140px;
  }

  .work__head { max-width: none; }
  .work__head h1 { font-size: 1.125rem; }

  /* The description runs the full 820px, matching the image above it, with the
     original's tighter 1.3 line-height — at 1.55 the lines drifted apart and
     the block read as cramped sideways and loose vertically at the same time.
     Lines run long at this width; that is the original's proportion. */
  .prose {
    max-width: none;          /* overrides the narrow measure used on a phone */
    font-size: 0.875rem;
    line-height: 1.3;
  }
  .prose p { margin: 0 0 1.3em; }

  /* 90px between images */
  .gallery figure + figure { margin-top: 90px; }
  /* captions at the original's caption size, 13px on an 18.2px line, and as
     wide as the picture, like the description above */
  .gallery figcaption { max-width: none; font-size: 13px; line-height: 18.2px; }
  .lightbox__caption { font-size: 13px; line-height: 18.2px; }

  /* CV: 130px indent inside the same 960px row, giving an 830px column */
  .cv {
    max-width: 60rem;
    margin-inline: auto;
    padding-left: 130px;
    font-size: 0.875rem;
  }
  /* the name at the original's 18px, the same size as a project title here */
  .cv__head h1 { font-size: 1.125rem; }

  /* Contact: 300px indent, giving a 660px column, set at the original's
     14px/1.3 — on a phone it stays 16px so an address is still easy to read.
     The 41px drop starts the name level with the dot in the menu: the dot's
     33px row is centred at 129.5px, the name's 17.5px line at 80 + 41 + 8.75. */
  .contact {
    width: auto;
    max-width: 60rem;
    margin-inline: auto;
    padding: 41px 0 0 300px;
    font-size: 0.875rem;
    line-height: 1.3;
  }
  .contact > h1,
  .contact address,
  .contact__reach { width: auto; max-width: none; }
  /* and the original's spacing: one blank line after the name, the email and
     phone as plain consecutive lines 14px below the address, 45px before the
     photo */
  .contact address  { margin-top: 1.3em; }
  .contact__reach   { margin-top: 14px; line-height: inherit; }
  .contact__reach a { padding-block: 0; }
  .contact__image   { margin-top: 45px; }
}

/* Between the sidebar breakpoint and about 1200px the content is centred in a
   viewport narrow enough that the smallest indent (130px, on the CV) no longer
   clears the fixed nav — in the original the CV text runs underneath it there.
   Hold the content clear in that band only; from 1200px up the natural
   centring already clears and the layout is left exactly as measured. */
@media (min-width: 981px) and (max-width: 1199px) {
  main { padding-left: 90px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* Following a link holds the current page on screen, unchanged, while the next
   one loads underneath, then switches straight to it: no dissolve, and no
   half-built page with its pictures still arriving. The script at the top of
   each page ends the hold as soon as the fonts and the pictures in view are
   ready; the 2s is only a ceiling, so a slow connection is never stuck on the
   old page. Without that script the switch comes as soon as the text can be
   drawn. Safari 18.2+ and Chrome 126+; anything older navigates as before.
   Nothing moves, so there is nothing for reduced motion to turn off. */
@view-transition { navigation: auto; }
::view-transition-group(root),
::view-transition-old(root),
::view-transition-new(root) { animation: none; }
@keyframes hold-page { from, to { opacity: 1; } }
.hold-page::view-transition-old(root) { animation: hold-page 2s; }
.hold-page::view-transition-new(root) { opacity: 0; }
