/* ==========================================================================
   ARCHIVE — a skin over lib/markup.js. No markup of its own.

   THE BRIEF, IN FIVE LINES
   Contemporary art catalogue × Berlin underground × artist archive × high-end
   gallery × personal world. Professional but not sterile. The art always
   matters more than the interface. Negative space, no colour of its own, no
   cards, no rounded anything, no glass, no gradients, no decorative icons.

   THE RULES THIS SKIN HOLDS ITSELF TO
   1. ONE GROUND. Near-black everywhere; --ink-lift only where a field must
      actually separate (the manifest, a metadata block, the panel, the
      footer). There is no second colour field on this site.
   2. NO COLOUR IN THE INTERFACE. Ink, paper and two greys; the paintings are
      the only colour on any page. This replaced an accent that each work
      derived from its own five dominant colours — measured, and handsome, and
      exactly what the design brief rules out: an interface tinted by the
      picture next to it. The active navigation item, a hover and the inquire
      action now carry by weight, by a line, or by inverting ink and paper.
   3. TWO TYPE SCALES AND NOTHING IN BETWEEN. Bricolage Grotesque 800,
      uppercase, tight, clamp(2.5rem, 12vw, 9rem); IBM Plex Mono 400/600 at
      11–12px, .08em, uppercase, tabular. Running text is Bricolage 400 at
      17–19px over at most 62ch. There is no 24px semi-heading anywhere.
   4. NOTHING IS DRAWN AROUND A PICTURE. No border, plate, frame, shadow or
      grey mat. Separation is the ground, the spacing and the scale. Hairlines
      exist only in mono contexts — a spec row, a table, a control — where they
      are the record's own ruling, never a frame.
   5. NEVER LARGER THAN THE SOURCE. Every picture is capped at its own
      --srcw, and rows are packed from each work's real --ar. No crop anywhere:
      `object-fit: cover` does not appear in this file.

   MEASURED CONTRAST (WCAG 2.2, computed not eyeballed)
     paper   #F4F1EA on ink #0E0E10       17.10:1     on lift #17171A  15.86:1
     dim     #A8A49B on ink                7.76:1     on lift           7.20:1
     ink     #0E0E10 on paper #F4F1EA     17.10:1  — the inquire action, which
             used to be paper on a work's own accent and measured 1.43:1.
   ========================================================================== */

@layer reset, base, chrome, blocks, art, archive, filter, motion;

/* ---------------------------------------------------------------- reset -- */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; }
  body, h1, h2, h3, h4, p, figure, figcaption, blockquote, dl, dd, ul, ol, li,
  table, th, td, caption, fieldset { margin: 0; padding: 0; }
  ul, ol { list-style: none; }
  img { display: block; max-width: 100%; height: auto; border: 0; background: none; box-shadow: none; }
  a { color: inherit; }
  button { font: inherit; color: inherit; background: none; border: 0; }
  table { border-collapse: collapse; border-spacing: 0; }
  th { text-align: left; font-weight: inherit; }
  sup { font-size: .58em; line-height: 0; vertical-align: super; }
}

/* ----------------------------------------------------------------- base -- */
@layer base {
  :root {
    /* the ground, per docs/CONCEPT-V3.md §10 */
    --ink:       #0E0E10;   /* near-black, the ground */
    --ink-lift:  #17171A;   /* one shade up, for a field that must separate */
    --paper:     #F4F1EA;   /* warm off-white */
    --paper-dim: #A8A49B;   /* secondary text — 7.76:1 on ink */

    /* the same oxblood lifted until 11px mono clears AA on the ground. One
       the ground and two greys; nothing here is chromatic. */

    /* the record's own ruling. A hairline is not a frame: it appears in mono
       contexts only and never around a picture. */
    --rule:        #26262A;
    --rule-strong: #3B3B41;

    --pad:  clamp(1.15rem, 5.2vw, 4.5rem);
    --gap:  clamp(.9rem, 2.4vw, 2rem);
    --maxw: 1560px;
    --bar:  3.5rem;
    /* viewport edge to the content edge of a .band-in */
    --edge: max(var(--pad), calc((100vw - var(--maxw)) / 2 + var(--pad)));
    --bp:   clamp(3.5rem, 11vw, 9rem);    /* band padding-block */

    --sans: 'Bricolage Grotesque', 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* SCALE ONE — display. The brief asked for extreme, so extreme. */
    --mega: clamp(2.5rem, 12vw, 9rem);
    --big:  clamp(2rem, 8vw, 5rem);
    /* SCALE TWO — the archive's own type. 11px to 12px, and no larger. */
    --ms:   clamp(.6875rem, .64rem + .18vw, .75rem);
    /* running text, and the only thing between the two scales */
    --read: clamp(1.0625rem, 1rem + .32vw, 1.1875rem);

    color-scheme: dark;
    accent-color: var(--paper);
    scroll-padding-top: calc(var(--bar) + 1.5rem);
  }
  @media (min-width: 900px) { :root { --bar: 4rem; } }

  /* THE DOCUMENT DOES NOT SCROLL — body does. That is the whole trick, and it is not a
     preference.

     A root scroller rubber-bands past its top edge on macOS and iOS, and everything inside it
     rides the bounce: a `position: sticky` header travels down with the page and opens a strip of
     bare --ink above itself, which reads as a black gap over the navigation. Safari does not
     honour overscroll-behavior on the root element, so there is no way to switch that off from
     here — the bounce belongs to the viewport, not to a box we can style.

     So the scroller becomes a real element. `html` is a fixed-size, non-scrolling box; `body`
     fills it and scrolls its own content; and because body is now an ordinary nested scroller,
     overscroll-behavior-y: none actually applies and there is no elastic travel left to ride.
     .site-head sticks to body's top edge and stays welded to it.

     Consequences, so nobody re-derives them: scroll-padding-top and scroll-behavior have to live
     on body, because that is the scrolling box the jump marks land in — on html they would apply
     to a box that never scrolls. Nothing in themes/archive/assets/site.js reads window.scrollY,
     and its IntersectionObserver and animation-timeline: view() both resolve against the nearest
     scroll container, so both keep working. */
  html { background: var(--ink); height: 100%; overflow: hidden; }
  @media (prefers-reduced-motion: no-preference) { body { scroll-behavior: smooth; } }

  /* The <symbol> sprite lib/brand.js writes before the header. It carries width="0" height="0",
     which sizes the box and does nothing about the LINE the box sits on: an inline element still
     opens a line box of body line-height, and those 28.5px landed as a strip of bare --ink above
     .site-head and pushed the navigation down the page. Taking it out of flow is the fix; absolute
     rather than display:none, because a hidden <symbol> must stay referenceable by <use>. */
  .sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

  body {
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior-y: none;
    scroll-padding-top: calc(var(--bar) + 1.5rem);
    background: var(--ink);
    color: var(--paper);
    font-family: var(--sans);
    font-optical-sizing: auto;
    font-weight: 400;
    font-size: var(--read);
    line-height: 1.5;
    text-wrap: pretty;
    -webkit-font-smoothing: antialiased;
  }

  ::selection { background: var(--paper); color: var(--ink); }

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

  .skip {
    position: fixed;
    inset-block-start: .5rem;
    inset-inline-start: .5rem;
    z-index: 200;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 1.15rem;
    background: var(--paper);
    color: var(--ink);
    font: 600 var(--ms)/1 var(--mono);
    letter-spacing: .12em;
    text-transform: uppercase;
    text-decoration: none;
    transform: translateY(-320%);
    transition: transform .18s;
  }
  .skip:focus { transform: none; }

  .vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

  /* ---- SCALE ONE: the display type -------------------------------------- */
  h1, h2, h3 { font-family: var(--sans); font-weight: 800; }

  .band-title {
    font-size: var(--mega);
    font-weight: 800;
    font-stretch: 78%;
    line-height: .84;
    letter-spacing: -.04em;
    text-transform: uppercase;
    text-wrap: balance;
    color: inherit;
  }
  .band-title a { text-decoration: none; }
  /* A neutral interface cannot signal a hover with a colour, so it signals it with a line. The
     accent used to do this; underlining is the plainer answer and does not compete with a
     painting next to it. */
  .band-title a:hover, .band-title a:focus-visible { text-decoration: underline; text-underline-offset: .12em; }

  .band-subtitle {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .3rem 1.1rem;
    font-size: var(--big);
    font-weight: 800;
    font-stretch: 76%;
    line-height: .86;
    letter-spacing: -.035em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums lining-nums;
  }
  .band-subtitle a { text-decoration: none; }
  .band-subtitle-count {
    font-family: var(--mono);
    font-size: var(--ms);
    font-weight: 400;
    font-stretch: 100%;
    letter-spacing: .16em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--paper-dim);
  }

  /* ---- SCALE TWO: the archive's mono ----------------------------------- */
  .kicker, .crumbs, .facts li, .work-title, .more a, .footnote, .site-nav-list a,
  .series-nav-list a, .series-card-count, .work-year, .cv dt, .work-spec dt,
  .work-spec dd, .exhibition-facts dt, .exhibition-facts dd, .themes li,
  .to-verify, .series-origin, .obs-label, .work-spec-note, .section-index a,
  .archive th, .archive td, .archive-summary li, .enquire, .work-nav b,
  .exhibition-card-meta, .site-footer a, .footer-note, .footer-meta,
  .work-filter-count, .work-filter-clear, .work-filter-field > label {
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .08em;
    font-variant-numeric: tabular-nums lining-nums;
  }
  .num { font-variant-numeric: tabular-nums lining-nums; }

  .kicker {
    display: block;
    margin-bottom: clamp(1rem, 3vw, 1.6rem);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }

  /* ---- running text: the one thing between the scales ------------------ */
  .lede, .prose p, .series-card-blurb, .series-disclaimer, .work-filter-empty {
    font-size: var(--read);
    line-height: 1.5;
    max-width: 62ch;
  }
  .lede { margin-top: clamp(1.1rem, 3vw, 1.75rem); color: var(--paper); }
  .prose { max-width: 62ch; }
  .prose p { color: var(--paper-dim); margin-bottom: .9em; }
  .prose p:last-child { margin-bottom: 0; }
  .prose .lede { margin-top: 0; color: var(--paper); }
  .prose a { color: var(--paper); text-underline-offset: .22em; }

  .pull {
    margin: clamp(1.75rem, 5vw, 3rem) 0;
    padding-left: clamp(1rem, 3vw, 1.75rem);
    border-left: 2px solid var(--rule-strong);
  }
  .pull p {
    color: var(--paper);
    font-size: clamp(1.25rem, 1rem + 1.6vw, 1.75rem);
    font-weight: 500;
    line-height: 1.25;
    letter-spacing: -.015em;
    max-width: 48ch;
  }

  .footnote {
    margin-top: clamp(1.5rem, 4vw, 2.25rem);
    line-height: 1.75;
    color: var(--paper-dim);
    max-width: 74ch;
  }
  .footnote a { color: var(--paper); }

  /* ---- the one remaining truthfulness mark -----------------------------
     The dagger on an unconfirmed title (.unconfirmed, five selectors, carefully clamped so it
     could not become a 60px crucifix inside a 9rem headline) is gone: titles come from the studio
     now, so there is nothing left to mark. Only .to-verify survives, and only for exhibitions,
     where a missing date is a real gap in a documented record. It is dimmed rather than coloured
     — uppercase mono at reading weight already reads as a field state rather than as an error. */
  .to-verify {
    color: var(--paper-dim);
    text-transform: uppercase;
    letter-spacing: .16em;
    font-weight: 400;
    white-space: nowrap;
  }

  /* .series-origin (the PROPOSED box) and .series-disclaimer stood here. Both went out with
     series.origin: every grouping in the catalogue is the studio's own, so neither class is
     rendered any more. They were also two of the seven places the interface took its colour from
     a painting. */

  /* ---- icons: inline SVG from lib/markup.js, stroke: currentColor.
     They mark a channel (mail, phone, Instagram, an external link) and nothing
     else — there is no decorative icon in this skin. ---- */
  .icon { flex: none; width: max(15px, 1.05em); height: max(15px, 1.05em); stroke-width: 1.6; vertical-align: -.16em; }
  .icon-external { width: max(12px, .8em); height: max(12px, .8em); stroke-width: 2; }
  .footer-contact a, .contact-links a, .site-social,
  .cv dd a, .work-spec dd a, .facts li a { display: inline-flex; align-items: center; gap: .55em; }
}

/* --------------------------------------------------------------- chrome --
   One slim bar on every page: the mark, the seven main links from 1100px up,
   and a Menu button at every width opening the whole navigation — the ten
   series included — as a full-screen type-only panel in the thumb arc.

   Everything is plain links in the HTML. The collapse is CSS gated on the `js`
   class site.js sets, so with JavaScript blocked the header is simply a
   two-row bar with every link and every series visible.
   ----------------------------------------------------------------------- */
@layer chrome {
  .site-head {
    position: sticky;
    inset-block-start: 0;
    z-index: 90;
    background: var(--ink);
    color: var(--paper);
    box-shadow: inset 0 -1px 0 var(--rule);
  }

  .site-head-bar {
    display: flex;
    align-items: center;
    gap: clamp(.5rem, 2vw, 2rem);
    max-width: var(--maxw);
    margin-inline: auto;
    padding-inline: var(--pad);
    min-height: var(--bar);
  }

  .site-brand {
    display: flex;
    align-items: center;
    gap: .55rem;
    flex: none;
    min-height: 44px;
    margin-right: auto;
    text-decoration: none;
  }
  .site-brand-mark { flex: none; display: flex; color: var(--paper); }
  .brand-m { display: block; width: auto; height: 1rem; aspect-ratio: 1.7274; }
  .site-brand-name {
    font-weight: 800;
    font-stretch: 76%;
    font-size: clamp(.95rem, .85rem + .5vw, 1.15rem);
    letter-spacing: .02em;
    text-transform: uppercase;
  }

  /* ---- the Menu button: present at every width once JS is running ---- */
  .site-nav-toggle {
    flex: none;
    order: 9;
    display: none;
    align-items: center;
    gap: .6rem;
    min-height: 44px;
    min-width: 44px;
    padding-inline: .3rem;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
  }
  :root.js .site-nav-toggle { display: inline-flex; }
  .site-nav-toggle::after {
    content: "";
    width: 20px;
    height: 7px;
    border-block: 1px solid currentColor;
    transition: transform .3s;
  }
  .site-nav-toggle[aria-expanded="true"]::after { transform: scaleY(.15); }

  /* ---- the main links ---- */
  .site-nav { min-width: 0; }
  .site-nav-list { display: flex; flex-wrap: wrap; gap: 0 clamp(.9rem, 1.5vw, 1.75rem); }
  .site-nav-list a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    position: relative;
    letter-spacing: .16em;
    text-transform: uppercase;
    white-space: nowrap;
    text-decoration: none;
    color: var(--paper-dim);
    transition: color .25s;
  }
  .site-nav-list a:hover, .site-nav-list a:focus-visible { color: var(--paper); }
  /* The current page. The bar's links sit at --paper-dim, so the one you are on is the one at
     full paper, and the 2px rule under it carries the rest. It used to be the accent's lifted
     value; nothing in the bar is coloured now. */
  .site-nav-list a[aria-current="page"] { color: var(--paper); }
  .site-nav-list a[aria-current="page"]::after {
    content: "";
    position: absolute;
    inset: auto 0 10px 0;
    height: 2px;
    background: var(--paper);
  }

  /* the one icon-only link on a narrow screen: it keeps its accessible name
     from the markup's .vh span, and a 44px box of its own */
  .site-social {
    flex: none;
    order: 8;
    display: none;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .1em;
    text-decoration: none;
    color: var(--paper-dim);
  }
  .site-social:hover, .site-social:focus-visible { color: var(--paper); }
  .site-social .icon { width: 18px; height: 18px; }
  .site-social-handle {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  @media (min-width: 560px) { .site-social { display: inline-flex; } }
  @media (min-width: 1320px) {
    .site-social { justify-content: flex-start; }
    .site-social-handle { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }
  }

  /* ---- the ten series, second row ---- */
  .series-nav { max-width: var(--maxw); margin-inline: auto; padding: 0 var(--pad) .4rem; }
  .series-nav-label {
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--paper-dim);
    margin-bottom: .15rem;
  }
  .series-nav-list { display: flex; flex-wrap: wrap; gap: 0 1rem; }
  .series-nav-list a {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-height: 44px;
    letter-spacing: .06em;
    white-space: nowrap;
    text-decoration: none;
    color: var(--paper-dim);
  }
  .series-nav-list a:hover, .series-nav-list a:focus-visible { color: var(--paper); }
  .series-nav-list a[aria-current] { color: var(--paper); }
  .series-nav-list a[aria-current="page"] { box-shadow: inset 0 -1px 0 var(--paper); }


  /* ---- no JavaScript: a two-row bar, every link visible, no button ---- */
  :root:not(.js) .site-head-bar { flex-wrap: wrap; row-gap: .1rem; padding-block: .35rem 0; }
  :root:not(.js) .site-brand { flex: 1 0 100%; margin-right: 0; min-height: 34px; }
  :root:not(.js) .site-nav { flex: 1 0 100%; }
  :root:not(.js) .site-nav-list a { min-height: 34px; }
  :root:not(.js) .series-nav-list a { min-height: 38px; }
  @media (min-width: 900px) {
    :root:not(.js) .site-head-bar { flex-wrap: nowrap; padding-block: 0; }
    :root:not(.js) .site-brand { flex: none; margin-right: auto; min-height: 44px; }
    :root:not(.js) .site-nav { flex: 0 1 auto; }
    :root:not(.js) .site-nav-list a, :root:not(.js) .series-nav-list a { min-height: 44px; }
  }

  /* ---- collapsed: only when site.js is alive ---- */
  :root.js .site-nav,
  :root.js .series-nav { display: none; }
  @media (min-width: 1100px) { :root.js .site-nav { display: block; } }

  /* ---- open: the header IS the panel. Type only, on the lifted field. ---- */
  /* The scroll lock goes on body, because body is the scroller (see the note on html above).
     On :root it would lock a box that never scrolls and the page would keep moving behind the
     open panel. */
  :root.js.nav-open body { overflow: hidden; }
  :root.js.nav-open .site-head {
    position: sticky;
    inset-block-start: 0;
    z-index: 120;
    height: 100dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--ink-lift);
    padding-bottom: 3rem;
    box-shadow: none;
  }
  :root.js.nav-open .site-head-bar {
    flex-wrap: wrap;
    row-gap: clamp(1.5rem, 5vw, 2.5rem);
    padding-block: 0 clamp(1rem, 3vw, 1.5rem);
  }
  :root.js.nav-open .site-nav { display: block; order: 10; flex: 1 0 100%; }
  :root.js.nav-open .site-nav-list { display: grid; }
  :root.js.nav-open .site-nav-list a {
    min-height: 56px;
    padding-block: .1rem;
    font-family: var(--sans);
    font-size: clamp(2rem, 1rem + 8vw, 3.25rem);
    font-weight: 800;
    font-stretch: 78%;
    letter-spacing: -.035em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--paper);
  }
  :root.js.nav-open .site-nav-list a::after { display: none; }
  :root.js.nav-open .site-nav-list a:hover,
  :root.js.nav-open .site-nav-list a:focus-visible,
  :root.js.nav-open .site-nav-list a[aria-current="page"] { color: var(--paper); }
  :root.js.nav-open .series-nav { display: block; padding-top: clamp(1.5rem, 5vw, 2.5rem); }
  :root.js.nav-open .series-nav-label { color: var(--paper-dim); margin-bottom: .8rem; }
  :root.js.nav-open .series-nav-list { display: grid; }
  :root.js.nav-open .series-nav-list a {
    font-family: var(--sans);
    font-size: clamp(1.05rem, .9rem + 1.4vw, 1.45rem);
    font-weight: 600;
    font-stretch: 88%;
    letter-spacing: -.01em;
    white-space: normal;
    color: var(--paper);
  }
  :root.js.nav-open .site-social {
    display: inline-flex;
    order: 11;
    flex: 1 0 100%;
    justify-content: flex-start;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--paper);
  }
  :root.js.nav-open .site-social-handle { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }
  @media (min-width: 780px) {
    :root.js.nav-open .site-nav-list,
    :root.js.nav-open .series-nav-list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3.5rem; }
  }

  /* ---- footer: the one other lifted field ---- */
  .site-footer {
    background: var(--ink-lift);
    color: var(--paper);
    padding-block: clamp(2rem, 4vw, 3rem);
    box-shadow: inset 0 1px 0 var(--rule);
  }
  .site-footer-in {
    max-width: var(--maxw);
    margin-inline: auto;
    padding-inline: var(--pad);
    display: grid;
    gap: clamp(1.25rem, 2vw, 2rem);
  }
  @media (min-width: 800px) {
    .site-footer-in { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .footer-mark { grid-column: 1 / -1; }
    .footer-note, .footer-meta { grid-column: 1 / -1; }
    /* The series list is the long one — as many rows as there are series, which grows with the
       catalogue. It gets two of the four columns and splits its links across them, so the footer
       stops being taller than the window it sits in. */
    .footer-series { grid-column: span 2; }
    .footer-series ul { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(1rem, 2vw, 2rem); }
  }
  .footer-nav ul, .footer-series ul, .footer-legal ul, .footer-contact { display: grid; align-content: start; }
  /* 44px per row is a FINGER target, and the footer is a list of sixteen links: at that height it
     stood 1000px tall on a 630px viewport — one and a half screens of link rows. So the tall row
     is kept where it is actually needed and dropped where a pointer does the aiming. Nothing here
     gets smaller than the text it contains, and the hover/focus area still spans the whole row. */
  .site-footer a {
    display: inline-flex;
    align-items: center;
    gap: .5em;
    min-height: 44px;
    letter-spacing: .06em;
    color: var(--paper-dim);
    text-decoration: none;
  }
  @media (pointer: fine) and (min-width: 800px) {
    .site-footer a { min-height: 0; padding-block: .25rem; }
  }
  .site-footer a:hover, .site-footer a:focus-visible { color: var(--paper); }
  .footer-series-label {
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--paper);
    margin-bottom: .3rem;
  }
  .footer-note, .footer-meta { line-height: 1.8; color: var(--paper-dim); max-width: 80ch; }
  .footer-mark { margin: 0; color: var(--paper); }
  .brand-m-foot { width: clamp(56px, 10vw, 84px); height: auto; }

  /* ---- legal pages (markup comes from build.js) ---- */
  .legal {
    max-width: var(--maxw);
    margin-inline: auto;
    padding: clamp(1.75rem, 6vw, 4rem) var(--pad) clamp(3rem, 9vw, 6rem);
  }
  .legal .site-head { margin: calc(-1 * clamp(1.75rem, 6vw, 4rem)) calc(-1 * var(--pad)) clamp(1.75rem, 6vw, 4rem); }
  .legal h1 {
    font-size: clamp(2rem, 1rem + 5vw, 4rem);
    font-stretch: 78%;
    line-height: .9;
    letter-spacing: -.035em;
    text-transform: uppercase;
    margin-bottom: .6rem;
  }
  .legal .legal-en { color: var(--paper-dim); font-weight: 400; }
  .legal h2 { font-size: 1rem; font-weight: 700; font-stretch: 92%; margin: 2rem 0 .5rem; }
  .legal p { color: var(--paper-dim); max-width: 62ch; margin-bottom: .8em; }
  .legal a { color: var(--paper); text-underline-offset: .22em; }
  .legal-back a, .legal-kicker, .legal-meta, .legal-lang {
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .14em;
    text-transform: uppercase;
  }
  .legal-back a { color: var(--paper); text-decoration: none; display: inline-flex; min-height: 44px; align-items: center; }
  .legal-kicker { color: var(--paper-dim); margin-bottom: 1.5rem; }
  .legal-meta { color: var(--paper-dim); letter-spacing: .08em; text-transform: none; }
  .legal .footer-legal ul { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 clamp(1.25rem, 4vw, 2rem); }
  .legal .footer-legal a {
    display: inline-flex;
    align-items: center;
    padding: 0 1rem;
    min-height: 44px;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .14em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--paper);
    box-shadow: inset 0 0 0 1px var(--rule-strong);
  }
  .legal .footer-legal a[aria-current="page"] { color: var(--ink); background: var(--paper); box-shadow: none; }
  .legal-summary {
    margin: 1.75rem 0;
    padding: clamp(1rem, 3vw, 1.75rem);
    background: var(--ink-lift);
  }
  .legal-summary p { color: var(--paper); }
  .legal-cols { display: grid; gap: clamp(2rem, 5vw, 4rem); margin-top: 2.5rem; }
  @media (min-width: 900px) { .legal-cols { grid-template-columns: 1fr 1fr; } }
  .legal-lang { color: var(--paper); font-size: var(--ms) !important; margin-top: 0 !important; }
  .legal-lang span { color: var(--paper-dim); }
}

/* --------------------------------------------------------------- blocks -- */
@layer blocks {
  .band {
    position: relative;
    padding-block: var(--bp);
    scroll-margin-top: calc(var(--bar) + .5rem);
  }
  /* --bp is the rhythm BETWEEN bands, and between two of them it is right. On the first band of a
     page it has nothing above it but the header, so it reads as a void rather than as spacing:
     144px of nothing between the menu and the first line. The rhythm is left alone; only the top
     of the first band is pulled in. */
  main > .band:first-child { padding-block-start: clamp(1.5rem, 4vw, 3rem); }

  .band-in { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--pad); }
  .band-in + .band-in { margin-top: clamp(1.75rem, 5vw, 3rem); }

  /* THE ONE LIFTED FIELD IN THE PAGE FLOW: the manifest. Nothing else on this
     site is a colour field, which is what makes this one read as a statement
     rather than as decoration. */
  [data-section="statement"] { background: var(--ink-lift); }

  /* ---- facts: a mono line, dot-separated. Not chips, not badges. ---- */
  .facts {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .35rem 1.1rem;
    margin-top: clamp(1.5rem, 4vw, 2.25rem);
  }
  .facts li {
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--paper-dim);
    white-space: nowrap;
  }
  /* the separator trails its own item, so a wrapped line never STARTS with a
     dot hanging in the margin */
  .facts li:not(:last-child)::after { content: "·"; margin-left: 1.1rem; color: var(--rule-strong); }
  .facts li a { color: var(--paper); min-height: 44px; text-underline-offset: .25em; }

  /* ---- the catalogue ribbon: static. One rail of mono facts between
     hairlines, and it does not move — the brief rules out animation that is
     there for its own sake. ---- */
  [data-section="ticker"] { padding-block: 0; }
  .ticker-list {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-inline: var(--pad);
    max-width: var(--maxw);
    margin-inline: auto;
    border-block: 1px solid var(--rule);
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }
  .ticker-list::-webkit-scrollbar { display: none; }
  .ticker-list li {
    flex: none;
    display: flex;
    align-items: center;
    gap: 1.4rem;
    padding-right: 1.4rem;
    min-height: 3rem;
    white-space: nowrap;
  }
  .ticker-list li:not(:last-child)::after { content: ""; flex: none; width: 3px; height: 3px; background: var(--rule-strong); }

  /* ---- the manifest ----
     Tuned for two or three words: --mega up to 144px, 800 weight, the face squeezed to 76% of its
     width, uppercase, and letters pulled 4.5% of their own size INTO each other. On a three-word
     slogan that reads as a poster. The statement is a sentence, and at that treatment a sentence
     is a wall of letters with no gaps in it.

     What was wrong was the combination on a 24-word sentence, not the treatment: at 144px with
     letters overlapping by 4.5% of their own size, in caps, it had no gaps left in it. So the
     display voice stays — Bricolage's condensed cut, 800, tight leading, tracking still slightly
     negative because that face is drawn for it — and only what a sentence cannot carry goes: the
     poster size, the caps, and tracking tight enough to close the counters. First attempt at this
     went too far the other way, to 100% width and zero tracking, which is not a lighter display
     face but no display face at all. If this ever holds three words again, restore the poster
     values from the git history rather than nudging these. */
  .statement-line {
    font-size: clamp(1.75rem, 3.6vw, 3.25rem);
    font-weight: 800;
    font-stretch: 85%;
    line-height: 1.08;
    letter-spacing: -.012em;
    max-width: 30ch;
    text-wrap: balance;
  }

  /* ---- section index: the year jump-marks on /works/ ---- */
  .section-index { margin-top: clamp(1.5rem, 4vw, 2.25rem); }
  .section-index ul { display: flex; flex-wrap: wrap; gap: .25rem .5rem; }
  .section-index a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 .85rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--paper-dim);
    box-shadow: inset 0 0 0 1px var(--rule);
    transition: color .2s, box-shadow .2s;
  }
  .section-index a:hover, .section-index a:focus-visible {
    color: var(--paper);
    box-shadow: inset 0 0 0 1px var(--rule-strong);
  }
  .section-index .to-verify { white-space: nowrap; }

  /* ---- more / crumbs ---- */
  .more { margin-top: clamp(1.75rem, 4vw, 2.5rem); }
  .more a {
    display: inline-flex;
    align-items: center;
    gap: .6rem;
    min-height: 44px;
    letter-spacing: .18em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--paper);
    box-shadow: inset 0 -1px 0 var(--rule-strong);
    transition: box-shadow .25s;
  }
  .more a:hover, .more a:focus-visible { box-shadow: inset 0 -1px 0 var(--paper); }

  .crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem .6rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }
  .crumbs a { color: var(--paper); text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
  .crumbs a:hover, .crumbs a:focus-visible { box-shadow: inset 0 -1px 0 currentColor; }

  /* ---- photographs: documentary, not artwork. A caption, nothing else. ---- */
  .photo, .portrait { margin-top: clamp(1.5rem, 4vw, 2.5rem); }
  .photo img, .portrait img { width: 100%; }
  .photo figcaption, .portrait figcaption, .work-detail figcaption, .hero-art figcaption {
    margin-top: .9rem;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .1em;
    line-height: 1.7;
    text-transform: uppercase;
    color: var(--paper-dim);
    max-width: 52ch;
  }
  /* the supplied jackets photograph is a phone screenshot with the status bar
     and app chrome baked into the top third; this trims it off. A documentary
     photograph, not a work — no painting is cropped anywhere in this file. */
  .photo:has(> img[src*="matribal-berlin-jackets"]) { overflow: hidden; }
  .photo:has(> img[src*="matribal-berlin-jackets"]) img { margin-top: -31.6%; }

  .exhibition-body, .shop-body, .studio-body, .feature-body, .contact-body {
    display: grid;
    gap: clamp(1.75rem, 5vw, 4rem);
    align-items: start;
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
  }
  @media (min-width: 820px) {
    .exhibition-body { grid-template-columns: minmax(0, .55fr) minmax(0, 1fr); }
    .shop-body, .studio-body, .contact-body { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  }
  @media (min-width: 1000px) {
    .feature-body { grid-template-columns: minmax(0, 1.5fr) minmax(0, .9fr); align-items: end; }
  }

  /* ---- mono rows: the archive's own ruling. Every dl on the site is one
     shape — label left, value right, a hairline between rows. ---- */
  .cv, .work-spec, .exhibition-facts {
    display: grid;
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
    border-top: 1px solid var(--rule);
  }
  .cv > div, .work-spec > div, .exhibition-facts > div {
    display: grid;
    gap: .25rem .5rem;
    padding-block: .8rem;
    border-bottom: 1px solid var(--rule);
  }
  @media (min-width: 560px) {
    .cv > div, .work-spec > div, .exhibition-facts > div {
      grid-template-columns: minmax(7.5rem, .26fr) minmax(0, 1fr);
      gap: 1.5rem;
      align-items: baseline;
    }
  }
  .cv dt, .work-spec dt, .exhibition-facts dt {
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }
  .cv dd { color: var(--paper); font-family: var(--sans); font-size: var(--read); }
  .work-spec dd, .exhibition-facts dd { color: var(--paper); letter-spacing: .04em; line-height: 1.6; }
  .cv dd a, .work-spec dd a, .exhibition-facts dd a {
    color: var(--paper);
    text-underline-offset: .25em;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* an unrecorded row is not a broken row: the label stays lit and only the
     value carries the mark */
  .work-spec-row[data-known="false"] dt { color: var(--paper-dim); }
  .work-spec-note {
    display: block;
    margin-top: .4rem;
    color: var(--paper-dim);
    letter-spacing: .04em;
    text-transform: none;
    line-height: 1.6;
    max-width: 52ch;
  }
  .work-spec dd .series-origin { margin-left: .5rem; }

  /* ---- what is OURS, said once and marked as ours ---- */
  .observation {
    margin: clamp(1.5rem, 4vw, 2.25rem) 0;
    padding: clamp(1rem, 3vw, 1.5rem);
    background: var(--ink-lift);
  }
  .observation p { color: var(--paper-dim); max-width: 58ch; margin-bottom: .6em; }
  .observation p:last-child { margin-bottom: 0; }
  .obs-label {
    display: block;
    margin-bottom: .8rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--paper) !important;
    max-width: 46ch;
  }

  .themes { display: flex; flex-wrap: wrap; gap: .3rem .5rem; margin-top: 1.5rem; }
  .themes li {
    padding: .4rem .7rem;
    letter-spacing: .1em;
    color: var(--paper-dim);
    box-shadow: inset 0 0 0 1px var(--rule);
  }

  /* ---- ACCENT USE 3 of 3: the inquire action. The single filled block on
     the site, and it is never beside a picture — it sits at the foot of the
     metadata column. Paper on oxblood is 4.58:1. ---- */
  .enquire {
    display: inline-flex;
    align-items: center;
    gap: .7rem;
    min-height: 48px;
    margin-top: 1.75rem;
    padding: 0 1.5rem;
    background: var(--paper);
    color: var(--ink);
    letter-spacing: .16em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background-color .25s;
  }
  .enquire:hover, .enquire:focus-visible { background: color-mix(in oklab, var(--paper) 86%, #000); }

  /* ---- contact: the links are the type ---- */
  .contact-links { display: grid; margin-top: clamp(1.75rem, 4vw, 2.5rem); }
  .contact-links a {
    display: flex;
    align-items: center;
    gap: .5em;
    padding-block: .3rem;
    min-height: 48px;
    font-weight: 700;
    font-stretch: 78%;
    font-size: clamp(1.15rem, .85rem + 3vw, 2.4rem);
    line-height: 1.1;
    letter-spacing: -.03em;
    text-decoration: none;
    overflow-wrap: anywhere;
    color: var(--paper);
  }
  .contact-links .icon { width: max(18px, .42em); height: max(18px, .42em); }
  /* These links are already at full paper, so a hover cannot be signalled by lifting the colour
     — it has to be a line. */
  .contact-links a:hover, .contact-links a:focus-visible { text-decoration: underline; text-underline-offset: .14em; }

  @media (min-width: 900px) {
    body:not(.page-contact) [data-section="contact"] .band-in {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      column-gap: clamp(2rem, 5vw, 6rem);
      align-items: start;
    }
    body:not(.page-contact) [data-section="contact"] .kicker        { grid-area: 1 / 1; }
    body:not(.page-contact) [data-section="contact"] .band-title    { grid-area: 2 / 1; }
    body:not(.page-contact) [data-section="contact"] .lede          { grid-area: 3 / 1; }
    body:not(.page-contact) [data-section="contact"] .contact-links { grid-area: 1 / 2 / 4 / 3; margin-top: .5rem; }
    body:not(.page-contact) [data-section="contact"] .footnote      { grid-area: 4 / 2 / 5 / 3; }
  }

  /* ---- series ---- */
  .series-list { display: grid; margin-top: clamp(1.75rem, 4vw, 2.5rem); }
  .series-card-name {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .4rem clamp(.8rem, 2vw, 1.5rem);
    font-size: var(--big);
    font-weight: 800;
    font-stretch: 76%;
    line-height: .9;
    letter-spacing: -.035em;
    text-transform: uppercase;
  }
  .series-card-name a {
    flex: 0 1 auto;
    display: flex;
    align-items: center;
    min-height: 48px;
    text-decoration: none;
    transition: color .25s;
  }
  .series-card-name a:hover, .series-card-name a:focus-visible { text-decoration: underline; text-underline-offset: .12em; }
  .series-card-count {
    flex: none;
    align-self: center;
    font-stretch: 100%;
    font-weight: 400;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }
  .series-card-blurb { margin-top: .8rem; color: var(--paper-dim); }
  .series-card .series-disclaimer { margin-top: .9rem; }

  /* the overview: one grouping per row, separated by a rule and by space —
     ten rooms, not ten cards */
  .page-series-index .series-card { padding-block: clamp(2rem, 5vw, 3.5rem); border-bottom: 1px solid var(--rule); }
  .page-series-index .series-card:first-child { border-top: 1px solid var(--rule); }
  @media (min-width: 900px) {
    .page-series-index .series-card {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
      grid-template-rows: auto auto auto 1fr;
      column-gap: clamp(2rem, 5vw, 5rem);
      align-items: start;
    }
    .page-series-index .series-card-name       { grid-column: 1; grid-row: 1; }
    .page-series-index .series-disclaimer      { grid-column: 1; grid-row: 2; }
    .page-series-index .series-card-blurb      { grid-column: 1; grid-row: 3; }
    .page-series-index .series-card-preview    { grid-column: 2; grid-row: 1 / span 4; margin-top: 0; }
  }

  /* ---- exhibitions ---- */
  .exhibition-list { display: grid; gap: clamp(2.5rem, 7vw, 4.5rem); margin-top: clamp(1.75rem, 4vw, 2.5rem); }
  .exhibition-card { display: grid; gap: .7rem; }
  .exhibition-card-name {
    font-size: var(--big);
    font-stretch: 76%;
    line-height: .88;
    letter-spacing: -.035em;
    text-transform: uppercase;
  }
  .exhibition-card-name a { text-decoration: none; }
  .exhibition-card-name a:hover, .exhibition-card-name a:focus-visible { text-decoration: underline; text-underline-offset: .12em; }
  .exhibition-card-meta { letter-spacing: .14em; text-transform: uppercase; color: var(--paper-dim); }
  .exhibition-card .exhibition-poster { margin-top: .5rem; width: min(100%, 340px); }
  .exhibition-views { display: grid; gap: clamp(1.75rem, 5vw, 3rem); }
  .exhibition-single .exhibition-poster img { width: min(100%, 720px); }
  .exhibition-works-note {
    margin-top: .5rem;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .06em;
    line-height: 1.8;
    color: var(--paper-dim);
    max-width: 70ch;
  }

  /* ---- 404 ---- */
  .page-404 .series-list { margin-top: clamp(2rem, 6vw, 3rem); border-top: 1px solid var(--rule); }
  .page-404 .series-card { border-bottom: 1px solid var(--rule); }
  .page-404 .series-card-name { font-size: clamp(1.35rem, 1rem + 2.4vw, 2rem); }
  .page-404 .contact-links a { font-size: clamp(1.35rem, 1rem + 2.6vw, 2rem); }
}

/* ------------------------------------------------------------------ art --
   THE RULE: nothing is drawn around a painting. No border, plate, frame,
   shadow or mat, and no crop — `object-fit` does not appear in this file.
   Separation is the ground, the spacing and the scale, and no picture is ever
   rendered wider than the pixels that exist (--srcw).
   ----------------------------------------------------------------------- */
@layer art {
  .work-image { width: 100%; height: auto; border: 0; box-shadow: none; background: none; }

  /* ======================================================= the homepage ==
     FOUR SCREENS (concept §3): the masthead, one work almost full-bleed, the
     manifest on its own field, then the doors. The bands after the manifest
     are reduced to type: a door is a kicker, a title and one mono link, and
     the picture that belongs to it lives on the page it opens.

     `main` becomes a column so the manifest can come before the doors without
     the markup being reordered. Nothing in it is focusable, so the reading
     order and the tab order stay the same sequence.
     ==================================================================== */
  .page-home main { display: flex; flex-direction: column; }
  .page-home [data-section="hero"]      { order: 1; }
  .page-home [data-section="ticker"]    { order: 2; }
  .page-home [data-section="statement"] { order: 3; }
  .page-home [data-section="works"]     { order: 4; }
  .page-home [data-section="series"]    { order: 5; }
  .page-home [data-section="feature"]   { order: 6; }
  .page-home [data-section="exhibition"]{ order: 7; }
  .page-home [data-section="shop"]      { order: 8; }
  .page-home [data-section="studio"]    { order: 9; }
  .page-home [data-section="contact"]   { order: 10; }

  /* ---- screen 1: the masthead. Type only, and the type is the hero. ---- */
  [data-section="hero"] { padding-block: 0; }
  [data-section="hero"] > .band-in { max-width: none; padding-inline: 0; }
  .hero-text {
    display: grid;
    align-content: center;
    min-height: calc(100svh - var(--bar));
    max-width: var(--maxw);
    margin-inline: auto;
    padding: clamp(3rem, 10vw, 7rem) var(--pad);
  }
  .hero-mark { margin: 0 0 clamp(1.5rem, 4vw, 2.5rem); color: var(--paper); }
  .brand-m-hero { width: min(62%, 22vw, 190px); height: auto; }

  .hero-line { max-width: 26ch; }
  .hero-line-a, .hero-line-b { display: block; }
  .hero-line-a {
    font-size: var(--mega);
    font-weight: 800;
    font-stretch: 76%;
    line-height: .84;
    letter-spacing: -.045em;
    text-transform: uppercase;
  }
  /* the manifest's second sentence: the same face, subordinate — a hierarchy
     inside the display scale, not a third scale */
  .hero-line-b {
    margin-top: .35em;
    font-size: clamp(1.4rem, 4.6vw, 2.6rem);
    font-weight: 400;
    font-stretch: 92%;
    line-height: 1.1;
    letter-spacing: -.02em;
    text-transform: none;
    max-width: 32ch;
    color: var(--paper);
  }
  [data-section="hero"] .lede { color: var(--paper-dim); max-width: 54ch; }

  /* ---- screen 2: one work, almost full-bleed, on the same ground ---- */
  .hero-art {
    display: grid;
    align-content: center;
    justify-items: center;
    min-height: 100svh;
    padding: clamp(2.5rem, 8vw, 6rem) var(--pad);
  }
  .hero-art .work-image {
    width: min(100%, var(--srcw), calc(var(--ar) * 68svh));
    margin-inline: auto;
  }
  .hero-art figcaption { margin-top: clamp(1.25rem, 3vw, 2rem); text-align: center; }
  .hero-art figcaption a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    letter-spacing: .18em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--paper);
    box-shadow: inset 0 -1px 0 var(--rule-strong);
  }
  .hero-art figcaption a:hover, .hero-art figcaption a:focus-visible { box-shadow: inset 0 -1px 0 var(--paper); }
  .hero-art .work-title-alt { display: inline; margin: 0; text-transform: none; letter-spacing: .04em; }

  /* ---- screen 3: the manifest ---- */
  .page-home [data-section="statement"] {
    display: grid;
    align-content: center;
    min-height: 100svh;
  }

  /* ---- screen 4: the doors ------------------------------------------------
     Everything after the manifest is a door: a kicker, a title and one mono
     link, ruled off top and bottom. The picture that belongs to each one lives
     on the page it opens — which is the concept's point about the homepage,
     and the reason it is four screens rather than ten sections.

     "Every band that is not one of the four screens" rather than a list of
     names, so a new section in lib/markup.js arrives as a door and not as a
     hole. --edge keeps a full-bleed rule while the type stays on the same
     measure as every other page.
     -------------------------------------------------------------------- */
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]) {
    padding-block: 0;
    border-bottom: 1px solid var(--rule);
  }
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]):first-of-type,
  .page-home [data-section="works"] { border-top: 1px solid var(--rule); }

  /* a door carries no pictures, no prose and no metadata of its own */
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"])
    :is(.work-list, .series-list, .work-plate, .photo, .portrait, .cv, .facts,
        .footnote, .lede, .prose p:not(.more), blockquote, .exhibition-poster) { display: none; }

  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]) .band-in {
    padding-block: clamp(1.5rem, 4vw, 2.5rem);
  }
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]) .band-in + .band-in {
    margin-top: 0;
    padding-top: 0;
  }
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]) .kicker {
    margin-bottom: .5rem;
  }
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"]) .band-title {
    font-size: clamp(1.9rem, 7vw, 4rem);
  }
  /* the layout wrappers that carried a picture beside the prose collapse */
  .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                              [data-section="statement"], [data-section="contact"])
    :is(.exhibition-body, .shop-body, .studio-body, .feature-body, .prose, .more) {
    display: block;
    margin-top: .5rem;
    gap: 0;
  }

  @media (min-width: 760px) {
    /* the title and the door it opens on one line. The band itself is the grid
       and the .band-in wrappers step out of the way, so a band split over two
       .band-in blocks (the works door) still lands on one row. */
    .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                                [data-section="statement"], [data-section="contact"]) {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      align-items: end;
      column-gap: clamp(1.5rem, 4vw, 3rem);
      padding: clamp(1.75rem, 4vw, 2.75rem) var(--edge);
    }
    .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                                [data-section="statement"], [data-section="contact"]) > .band-in {
      display: contents;
    }
    .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                                [data-section="statement"], [data-section="contact"]) .kicker {
      grid-area: 1 / 1;
    }
    .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                                [data-section="statement"], [data-section="contact"]) .band-title {
      grid-area: 2 / 1;
    }
    .page-home main > .band:not([data-section="hero"], [data-section="ticker"],
                                [data-section="statement"], [data-section="contact"])
      :is(.exhibition-body, .shop-body, .studio-body, .feature-body, .more) {
      grid-area: 2 / 2;
      justify-self: end;
      margin-top: 0;
    }
  }
  .page-home [data-section="contact"] { padding-top: clamp(3rem, 9vw, 6rem); }

  /* ======================================================== the hang ====
     Rows are packed from each work's own aspect ratio and capped at its own
     pixels: one large, two small, one wide, one tall, per group — the rhythm
     is the pictures' own proportions, not a taste decision (concept §4).
     ==================================================================== */
  .work-list { display: grid; gap: clamp(2.25rem, 8vw, 3.5rem); }
  .work-item { min-width: 0; max-width: min(100%, var(--srcw)); }

  /* 390px first: one work per screen, widths alternating, so a 380px source
     sits at or near its true resolution instead of being stretched. */
  @media (max-width: 679px) {
    .work-item:nth-child(4n+2) { width: 78%; margin-inline-start: auto; }
    .work-item:nth-child(4n+3) { width: 90%; }
    .work-item:nth-child(4n+4) { width: 66%; margin-inline-start: auto; }
  }

  @media (min-width: 680px) {
    .work-list {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-end;
      gap: clamp(2.5rem, 6vw, 5rem) var(--gap);
      --row-h: clamp(13rem, 27vw, 18rem);
    }
    /* basis AND grow are the work's own ratio, so a row lands on one shared
       height with no crop and no fixed ratio; the ::after spacer absorbs the
       free space on the LAST row only, so a two-member row keeps the scale of
       a full one. */
    .work-item { flex: var(--ar) 0 calc(var(--ar) * var(--row-h)); width: auto; max-width: min(100%, var(--srcw), 42vw); }
    .work-list::after { content: ""; flex: 999999 0 0; }
    .work-item:nth-child(6n+1) { --row-h: clamp(17rem, 40vw, 27rem); }   /* the large one */
    .work-item:nth-child(6n+4) { --row-h: clamp(15rem, 33vw, 22rem); }
    .work-item:nth-child(6n+3) { margin-bottom: clamp(1.5rem, 5vw, 4rem); }
  }
  @media (min-width: 1024px) {
    .work-list { --row-h: clamp(14rem, 17vw, 19rem); }
    .work-item { max-width: min(100%, var(--srcw), 38vw); }
    .work-item:nth-child(6n+1) { --row-h: clamp(18rem, 25vw, 26rem); }
    .work-item:nth-child(6n+4) { --row-h: clamp(16rem, 20vw, 21rem); }
  }

  .work-link { display: block; text-decoration: none; -webkit-tap-highlight-color: transparent; }
  .work-figure { display: block; }

  /* The title is always in the DOM and always visible — §13 forbids
     hover-only information. Hover and focus only lift it out of the dim. */
  .work-title {
    display: block;
    margin-top: .9rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--paper-dim);
    overflow-wrap: anywhere;
    transition: color .3s;
  }
  .work-title-alt {
    display: block;
    margin-top: .25rem;
    text-transform: none;
    letter-spacing: .04em;
    line-height: 1.6;
  }
  @media (hover: hover) {
    .work-link:hover .work-title { color: var(--paper); }
    /* the rest of the hang steps back, so the one being looked at is the
       brightest thing on the page — the only "effect" over a picture here */
    .work-list:has(.work-link:hover) .work-item:not(:hover) { opacity: .5; }
    .work-item { transition: opacity .4s; }
  }
  .work-link:focus-visible .work-title { color: var(--paper); }

  /* ---- the year groups on /works/ ---- */
  .band-part { padding-block: clamp(2.5rem, 7vw, 4.5rem); }
  .band-part + .band-part { border-top: 1px solid var(--rule); }
  .band-part .band-subtitle { margin-bottom: clamp(1.5rem, 4vw, 2.5rem); }
  .band-part .band-subtitle .to-verify { letter-spacing: .06em; }

  /* ======================================================== a work page == */
  .page-work [data-section="work"] { padding-block: clamp(1.5rem, 4vw, 2.5rem) var(--bp); }
  .work-plate { width: min(100%, var(--srcw)); margin-inline: auto; }
  .work-plate a { display: block; }
  .work-plate .work-image { width: 100%; }
  /* bounded by the viewport's HEIGHT through the work's own ratio, so a 0.43:1
     canvas and a 1.73:1 canvas both land on screen with their title — a height
     cap, never a crop */
  @media (min-width: 900px) {
    .page-work .work-plate { width: min(100%, var(--srcw), 66vw, calc(var(--ar) * 78svh)); }
  }
  @media (min-width: 1000px) {
    [data-section="feature"] .work-plate { width: min(100%, var(--srcw), 56vw); }
  }

  .work-head {
    display: grid;
    gap: .6rem;
    margin-top: clamp(2rem, 6vw, 3.5rem);
    container-type: inline-size;
  }
  .page-work .work-head .band-title {
    font-size: clamp(2.5rem, 15cqi, 9rem);
    line-height: .82;
    letter-spacing: -.045em;
    text-transform: uppercase;
  }
  .work-year { letter-spacing: .22em; color: var(--paper-dim); }
  .page-work .work-title-alt {
    display: block;
    margin-top: 1rem;
    font-family: var(--mono);
    font-size: var(--ms);
    letter-spacing: .04em;
    line-height: 1.8;
    color: var(--paper-dim);
    text-transform: none;
    max-width: 62ch;
  }
  .work-body { display: grid; gap: clamp(2rem, 6vw, 4.5rem); margin-top: clamp(2rem, 5vw, 3.5rem); align-items: start; }
  @media (min-width: 900px) {
    .work-body { grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); }
  }
  .work-aside .kicker { margin-bottom: .5rem; }
  .work-details { display: grid; gap: clamp(1.5rem, 4vw, 2.5rem); margin-top: clamp(1.5rem, 4vw, 2.5rem); }
  .work-detail img { width: min(100%, 420px); }

  .work-nav {
    display: grid;
    margin-top: clamp(3rem, 8vw, 5rem);
    border-top: 1px solid var(--rule);
  }
  @media (min-width: 620px) { .work-nav { grid-template-columns: 1fr 1fr; } }
  .work-nav a {
    display: grid;
    gap: .4rem;
    padding: clamp(1rem, 3vw, 1.5rem) 0;
    text-decoration: none;
    border-bottom: 1px solid var(--rule);
    transition: color .25s;
  }
  @media (min-width: 620px) {
    .work-nav a:last-child { text-align: right; padding-left: clamp(1rem, 3vw, 2rem); }
    .work-nav a:first-child { padding-right: clamp(1rem, 3vw, 2rem); }
  }
  .work-nav a:hover, .work-nav a:focus-visible { text-decoration: underline; text-underline-offset: .12em; }
  .work-nav b { font-weight: 400; letter-spacing: .18em; text-transform: uppercase; color: var(--paper-dim); }
  .work-nav span {
    font-weight: 700;
    font-stretch: 78%;
    font-size: clamp(1.1rem, .95rem + 1.4vw, 1.75rem);
    letter-spacing: -.03em;
    line-height: 1.1;
    text-transform: uppercase;
  }

  /* ---- "more from this series": a rail, so a long series never dominates */
  .related .work-list {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    gap: var(--gap);
    align-items: flex-start;
    padding: .25rem var(--pad) 1.5rem;
    margin-inline: calc(var(--pad) * -1);
    scroll-padding-inline-start: var(--pad);
    overscroll-behavior-x: contain;
  }
  .related .work-list::-webkit-scrollbar { display: none; }
  .related .work-item { flex: 0 0 auto; width: auto; max-width: none; margin: 0; scroll-snap-align: start; }
  .related .work-image { width: auto; max-width: none; height: clamp(140px, 18vw, 180px); }
  .related .work-title { max-width: 22ch; }

  /* ---- the series/ preview: pictures only, height-matched, never enlarged */
  .series-card-preview {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap);
    align-items: flex-end;
    margin-top: clamp(1.25rem, 3.5vw, 2rem);
  }
  .series-card-preview .work-item { flex: 0 0 auto; width: auto; margin: 0; max-width: min(100%, var(--srcw)); }
  .series-card-preview .work-image { width: auto; max-width: 100%; height: clamp(104px, 13vw, 190px); }
}

/* -------------------------------------------------------------- archive --
   /archive/ is the one page where metadata appears outside a work's own page
   (concept §2, §8): Works is edited and looks at you, the Archive is complete,
   flat and near-scientific. Almost no styling — mono, tabular, hairline-ruled,
   and built to still work at several hundred rows.

   Two things the markup deliberately leaves to the skin, and both are here:
   the scroll container, and the thumbnails' size.

   THE ACCENT STEPS BACK IN THIS TABLE. 74 rows of TO VERIFY in oxblood, each
   one a few centimetres from a thumbnail of a painting, is exactly the "within
   reach of a work" the concept rules out — and at 11px the block oxblood would
   not clear AA anyway. Here the mark carries by case and letterspacing, in
   --paper-dim at 7.76:1. Everywhere else it is the accent.
   ----------------------------------------------------------------------- */
@layer archive {
  .archive-summary { margin-top: clamp(1.5rem, 4vw, 2.25rem); }

  /* the one overflow container in the markup: the table scrolls inside itself
     rather than making the page scroll sideways */
  .archive-scroll { overflow-x: auto; overscroll-behavior-x: contain; }

  .archive { width: 100%; }
  .archive th, .archive td { letter-spacing: .06em; line-height: 1.5; }

  .archive-row .to-verify { color: var(--paper-dim); letter-spacing: .14em; }
  .archive-image {
    width: auto;
    height: auto;
    max-width: 72px;
    max-height: 58px;   /* a box it fits INSIDE — never a crop, never enlarged */
  }
  .archive-title { font-weight: 400; }
  .archive-title a { color: var(--paper); text-decoration: none; }
  .archive-title a:hover, .archive-title a:focus-visible { box-shadow: inset 0 -1px 0 currentColor; }
  .archive-title .work-title-alt {
    display: block;
    margin-top: .2rem;
    color: var(--paper-dim);
    letter-spacing: .02em;
  }
  .archive-series a { color: var(--paper); text-decoration: none; }
  .archive-series a:hover, .archive-series a:focus-visible { box-shadow: inset 0 -1px 0 currentColor; }
  /* nine of ten groupings are ours; in a dense table the box would be 64 boxes,
     so here the mark is the word alone */
  /* In the table the mark is plain text, not a box and not an inline-flex:
     74 boxes would be a pattern, and an atomic inline box inside a
     hanging-indent cell collides with its own wrapped line. */
  .archive-series .series-origin {
    display: inline;
    border: 0;
    padding: 0;
    min-height: 0;
    margin-left: .4rem;
    letter-spacing: .14em;
    translate: none;
    color: var(--paper-dim);
  }

  /* ---- 760px and up: a real table ---- */
  @media (min-width: 760px) {
    .archive { min-width: 62rem; }
    .archive-head th {
      position: sticky;
      inset-block-start: var(--bar);
      z-index: 2;
      padding: .7rem .9rem;
      background: var(--ink-lift);
      color: var(--paper);
      letter-spacing: .18em;
      text-transform: uppercase;
      white-space: nowrap;
      box-shadow: inset 0 -1px 0 var(--rule-strong);
    }
    .archive td, .archive tbody th { padding: .65rem .9rem; vertical-align: middle; border-bottom: 1px solid var(--rule); }
    .archive-thumb { width: 88px; padding-left: 0 !important; }
    .archive-year, .archive-dim { white-space: nowrap; }
    .archive-row { transition: background-color .2s; }
    .archive-row:hover { background: var(--ink-lift); }
  }

  /* ---- below 760px: a stacked list, not a squeezed table (concept §13).
     The column headings go with it and each value carries its own label, so
     nothing is announced twice and nothing depends on a remembered column. */
  @media (max-width: 759px) {
    .archive-head { display: none; }
    .archive, .archive tbody, .archive-row, .archive-row > td, .archive-row > th { display: block; }
    .archive { min-width: 0; }
    .archive-row {
      position: relative;
      min-height: 76px;
      padding: 1.1rem 0 1.2rem 88px;
      border-bottom: 1px solid var(--rule);
    }
    .archive-thumb { position: absolute; inset: 1.1rem auto auto 0; width: 72px; }
    .archive-title {
      font-family: var(--sans);
      font-size: 1.05rem;
      font-weight: 700;
      font-stretch: 84%;
      letter-spacing: -.02em;
      line-height: 1.15;
      margin-bottom: .6rem;
    }
    .archive-title .work-title-alt { font-family: var(--mono); font-size: var(--ms); font-weight: 400; }
    /* each value gets its own label, so nothing depends on a remembered
       column — a two-column mono list per row, the label in the first column
       so a wrapped value stays aligned under itself */
    /* A hanging indent rather than a grid: a cell can hold two inline things
       (the series link AND its PROPOSED mark), and grid would put the second
       one in the label column. */
    .archive-row > td:not(.archive-thumb) {
      padding: .14rem 0 .14rem 5.8em;
      text-indent: -5.8em;
      /* A long medium ("Acrylic and spray on canvas") ran into the right edge at 390px.
         Wrap it under the label instead of letting it touch the viewport. */
      padding-right: .9rem;
      overflow-wrap: break-word;
    }
    .archive-row > td:not(.archive-thumb)::before {
      display: inline-block;
      width: 5.8em;
      text-indent: 0;
      color: var(--paper-dim);
      letter-spacing: .16em;
      text-transform: uppercase;
    }
    .archive-row > td.archive-year::before   { content: "Year"; }
    .archive-row > td.archive-medium::before { content: "Medium"; }
    .archive-row > td.archive-dim::before    { content: "Size"; }
    .archive-row > td.archive-series::before { content: "Series"; }
    .archive-row > td.archive-status::before { content: "Status"; }
  }
}

/* --------------------------------------------------------------- filter --
   The one interactive island on the site, on /works/ and on /archive/.
   lib/markup.js renders .work-filter EMPTY; without the bundle the container
   has no children and, being display:contents, no box either — the page is
   then the complete list with no filter bar, which is what it was before.

   The controls are the archive's own furniture: a lifted rectangle, a 1px
   rule, a mono label above it. No radius, no shadow, no accent — a filter is
   not one of the accent's three jobs.
   ----------------------------------------------------------------------- */
@layer filter {
  .work-filter { display: contents; }
  .work-filter-form { margin-top: clamp(1.75rem, 4.5vw, 2.75rem); }

  .work-filter-fields { display: grid; gap: clamp(.7rem, 2vw, 1rem) var(--gap); }
  /* 390px: one control per row. Four rows of 48px beats a cramped two-up. */
  @media (min-width: 620px) {
    .work-filter-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .work-filter-field-search { grid-column: 1 / -1; }
  }
  @media (min-width: 1000px) {
    .work-filter-fields { grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr)); }
    .work-filter-field-search { grid-column: auto; }
  }

  .work-filter-field { display: grid; gap: .4rem; min-width: 0; }
  .work-filter-field > label {
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--paper-dim);
  }

  .work-filter-search,
  .work-filter-select {
    width: 100%;
    min-height: 48px;
    padding: 0 .9rem;
    border: 0;
    border-radius: 0;
    box-shadow: inset 0 0 0 1px var(--rule-strong);
    background: var(--ink-lift);
    color: var(--paper);
    font-family: var(--mono);
    font-size: .8rem;
    letter-spacing: .06em;
    line-height: 1.2;
    transition: box-shadow .2s;
  }
  .work-filter-search::placeholder { color: var(--paper-dim); }   /* 7.20:1 on the lift */
  .work-filter-search:hover,
  .work-filter-select:hover { box-shadow: inset 0 0 0 1px var(--paper-dim); }

  /* appearance:none means the arrow has to be supplied; drawn in two lines of
     the same off-white the label uses, so it belongs to the page rather than
     to the platform. background-color, never the shorthand — the shorthand
     would reset these. */
  .work-filter-select {
    appearance: none;
    padding-right: 2.4rem;
    background-image:
      linear-gradient(45deg, transparent 50%, var(--paper-dim) 50%),
      linear-gradient(135deg, var(--paper-dim) 50%, transparent 50%);
    background-position: calc(100% - 1.25rem) calc(50% + 1px), calc(100% - .95rem) calc(50% + 1px);
    background-size: 6px 6px, 6px 6px;
    background-repeat: no-repeat;
  }
  .work-filter-select option { background: var(--ink-lift); color: var(--paper); }

  .work-filter-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .6rem 1.5rem;
    margin-top: clamp(1rem, 3vw, 1.5rem);
  }
  .work-filter-count { letter-spacing: .16em; text-transform: uppercase; color: var(--paper); }
  .work-filter[data-active="true"] .work-filter-count { font-weight: 600; }

  .work-filter-clear {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 1.1rem;
    box-shadow: inset 0 0 0 1px var(--rule-strong);
    color: var(--paper-dim);
    letter-spacing: .16em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color .2s, box-shadow .2s;
  }
  .work-filter-clear:hover, .work-filter-clear:focus-visible {
    color: var(--paper);
    box-shadow: inset 0 0 0 1px var(--paper-dim);
  }

  .work-filter-empty { margin-top: clamp(1rem, 3vw, 1.5rem); color: var(--paper); }

  /* The island hides a non-match with the `hidden` attribute, so it leaves the
     accessibility tree as well as the page. The UA rule for `hidden` is weaker
     than any author `display`, and .work-item, .archive-row and .band-part all
     have one — so state it here once, for everything. */
  [hidden] { display: none !important; }
}

/* --------------------------------------------------------------- motion --
   ADDITIVE ONLY, and slow. One reveal — a picture arriving from slightly below
   as it enters — plus soft colour transitions and the cross-document fade.
   No parallax: it detaches a picture from its ground, which is the one lie a
   catalogue cannot tell.

   The plain state is the VISIBLE state. Every reveal is gated on both
   scroll-timeline support and a motion preference, so a browser without either
   — and a reader who asks for less — gets the page with nothing hidden. `.pre`
   is added by site.js and by nothing else, so with JS off it never exists.
   ----------------------------------------------------------------------- */
@layer motion {
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .work-item, .series-card, .photo, .portrait, .work-plate, .work-detail,
      .statement-line, .contact-links a, .cv > div {
        animation: rise linear both;
        animation-timeline: view();
        animation-range: entry 4% cover 26%;
      }
      /* a rail already moves sideways; a sideways reveal would fight it, and
         74 table rows animating is a fidget, not a reveal */
      .related .work-item, .series-card-preview .work-item, .archive-row { animation: none; }
    }
  }
  @keyframes rise {
    from { opacity: 0; transform: translateY(1.75rem); }
    to   { opacity: 1; transform: none; }
  }

  .pre { opacity: 0; transform: translateY(1.75rem); }
  .work-item, .series-card, .photo, .portrait, .work-plate, .statement-line {
    transition: opacity .8s cubic-bezier(.2, .7, .2, 1), transform .8s cubic-bezier(.2, .7, .2, 1);
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: .001ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: .001ms !important;
      scroll-behavior: auto !important;
    }
    .pre { opacity: 1 !important; transform: none !important; }
    .work-list:has(.work-link:hover) .work-item:not(:hover) { opacity: 1; }
  }

  /* Cross-document transition. Ignored where unsupported. */
  @view-transition { navigation: auto; }
  @media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: .32s; }
}

/* The header and the mark keep their identity across a cross-document
   navigation instead of cross-fading with the page body. */
.site-brand { view-transition-name: brand; }
.site-head  { view-transition-name: head; }
@media (prefers-reduced-motion: reduce) {
  .site-brand, .site-head { view-transition-name: none; }
}
