@charset "utf-8";

/* ============================================================ font
   Jost, served from this site rather than from Google Fonts (2026-09-19).
   Loading it from fonts.googleapis.com sent every visitor's IP address to
   Google on first paint, before any consent — while the privacy policy said
   nothing reaches a third party. Self-hosted, that sentence is true.
   These are the exact files Google served for this site (Jost v20, a variable
   font: one file covers weights 200-500), with Google's own unicode-range
   split: latin, plus latin-ext for the Polish letters ą ć ę ł ń ś ź ż.
   SIL Open Font License 1.1 — the licence travels with them: ../fonts/OFL.txt */
@font-face{
  font-family:"Jost";font-style:normal;font-weight:200 500;font-display:swap;
  src:url(../fonts/jost-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;
}
@font-face{
  font-family:"Jost";font-style:normal;font-weight:200 500;font-display:swap;
  src:url(../fonts/jost-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;
}

/* ============================================================ tokens */
:root{
  --paper:#F6F2EB;
  --paper-2:#EFE9DF;
  --paper-3:#E7DFD2;
  --dark:#22201D;

  --ink:#15120E;
  --ink-2:#4B453C;
  --muted:#8B8278;
  --on-dark:#EDE7DC;
  --on-dark-2:#A9A197;

  --clay:#A5735A;
  --rule:rgba(21,18,14,.14);
  --rule-2:rgba(21,18,14,.07);
  --rule-dark:rgba(237,231,220,.16);

  --sidebar:268px;
  --gut:clamp(20px,4.2vw,72px);
  --sec:clamp(64px,9vw,152px);

  --font-sans:"Jost","Futura","Century Gothic","Avenir Next",system-ui,-apple-system,"Segoe UI",sans-serif;

  --nav:13.5px;
  --track:.16em;
  --ease:cubic-bezier(.22,.61,.36,1);
}

/* ============================================================ base */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--font-sans);font-weight:300;font-size:16px;line-height:1.65;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
input,textarea,select{font:inherit;color:inherit}
h1,h2,h3,h4,p,figure,ul,ol,dl,dd{margin:0}
ul,ol{padding:0;list-style:none}
hr{border:0;border-top:1px solid var(--rule);margin:0}

::selection{background:var(--clay);color:#fff}

:focus-visible{outline:2px solid var(--clay);outline-offset:3px;border-radius:2px}

/* Present for screen readers and the heading outline, invisible on screen.
   First used for the Biografia page's section heading. */
.visually-hidden{
  position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}
.skip{
  position:fixed;left:-999px;top:12px;z-index:1000;
  background:var(--ink);color:var(--paper);padding:10px 18px;
  font-size:12px;letter-spacing:var(--track);text-transform:uppercase;
}
.skip:focus{left:12px}

.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ============================================================ type */
.eyebrow{
  font-size:12px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--muted);font-weight:500;
}
.d1{font-size:clamp(38px,6.4vw,86px);line-height:1.02;font-weight:200;letter-spacing:-.02em}
.d2{font-size:clamp(30px,4.4vw,60px);line-height:1.06;font-weight:200;letter-spacing:-.015em}
.d3{font-size:clamp(22px,2.6vw,34px);line-height:1.16;font-weight:250;letter-spacing:-.01em}
.h4{font-size:clamp(17px,1.5vw,21px);line-height:1.3;font-weight:400;letter-spacing:-.005em}
.lead{font-size:clamp(17px,1.55vw,21px);line-height:1.62;color:var(--ink-2);font-weight:300}
.body p+p{margin-top:1.1em}
.body{color:var(--ink-2);max-width:62ch}
/* a paragraph typed into a panel textarea; a span so it stays valid inside the
   <p>, <h2>, <figcaption> and <blockquote> these texts are emitted into */
.para{display:block}
.para+.para{margin-top:1.1em}
.measure{max-width:66ch}
.mono-meta{font-size:14px;letter-spacing:.05em;color:var(--muted)}

/* ============================================================ sidebar */
.sidebar{
  position:fixed;inset:0 auto 0 0;width:var(--sidebar);z-index:60;
  display:flex;flex-direction:column;
  padding:30px 26px 24px;
  background:var(--paper);border-right:1px solid var(--rule);
}
.brand{display:block;line-height:1.14;font-size:21px;font-weight:300;letter-spacing:-.01em}
.brand span{display:block}
.brand small{
  display:block;margin-top:9px;font-size:11.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);font-weight:400;
}
.nav{margin-top:44px}
.nav>li+li{margin-top:3px}
.nav a{
  display:block;padding:8px 0;position:relative;
  font-size:var(--nav);letter-spacing:.13em;text-transform:uppercase;font-weight:400;
  color:var(--ink-2);transition:color .35s var(--ease),transform .35s var(--ease);
}
.nav a::before{
  content:"";position:absolute;left:-26px;top:50%;width:16px;height:1px;
  background:var(--ink);transform:scaleX(0);transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav a:hover{color:var(--ink)}
.nav a[aria-current="page"],.nav li.is-open>a{color:var(--ink)}
.nav a[aria-current="page"]::before,.nav a:hover::before{transform:scaleX(1)}
/* nested navigation: a branch is a toggle, its children are the links */
.nav-toggle{
  display:block;width:100%;padding:8px 0;position:relative;text-align:left;
  font-size:var(--nav);letter-spacing:.13em;text-transform:uppercase;font-weight:400;
  color:var(--ink-2);transition:color .35s var(--ease);
}
.nav-toggle:hover{color:var(--ink)}
.nav-branch.is-open > .nav-toggle{color:var(--ink)}
.nav-toggle::before{
  content:"";position:absolute;left:-26px;top:50%;width:16px;height:1px;
  background:var(--ink);transform:scaleX(0);transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav-toggle:hover::before,.nav-branch.is-open > .nav-toggle::before{transform:scaleX(1)}

/* animate the row track, not a height, so nothing is clipped at any length */
.nav-sub-wrap{display:grid;grid-template-rows:0fr;transition:grid-template-rows .38s var(--ease)}
.nav-branch.is-open > .nav-sub-wrap{grid-template-rows:1fr}
.nav-sub-in{overflow:hidden;min-height:0}

.nav-sub{margin:2px 0 8px;padding-left:14px;border-left:1px solid var(--rule)}
.nav-sub a,.nav-sub .nav-toggle{
  font-size:11.5px;letter-spacing:.11em;padding:6px 0;color:var(--muted);
}
.nav-sub a::before,.nav-sub .nav-toggle::before{display:none}
.nav-sub a:hover,.nav-sub a[aria-current="page"],
.nav-sub .nav-toggle:hover,.nav-sub .nav-branch.is-open > .nav-toggle{color:var(--ink)}
.nav-sub--2{padding-left:12px}
.nav-sub--2 a{font-size:11px;letter-spacing:.1em}

.side-foot{margin-top:auto;padding-top:30px}
.socials{display:flex;gap:14px;align-items:center;margin-bottom:16px}
.socials a{
  width:22px;height:22px;display:grid;place-items:center;color:var(--ink-2);
  transition:color .3s var(--ease),transform .3s var(--ease);
}
.socials a:hover{color:var(--clay);transform:translateY(-2px)}
.socials svg{width:15px;height:15px;fill:currentColor}

.btn-news{
  display:inline-block;padding:9px 17px;margin-bottom:20px;
  background:var(--clay);color:#fff;
  font-size:11.5px;font-weight:400;letter-spacing:.16em;text-transform:uppercase;
  transition:background .35s var(--ease),transform .14s var(--ease);
}
.btn-news:hover{background:var(--ink)}

.legal{font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);line-height:2}
.legal a:hover{color:var(--ink)}

/* ============================================================ topbar */
.topbar{
  position:fixed;top:22px;right:22px;z-index:70;
  display:flex;align-items:center;gap:2px;
  background:var(--paper);border:1px solid var(--rule);border-radius:999px;
  padding:5px 6px;box-shadow:0 2px 18px rgba(21,18,14,.06);
}
.topbar button{
  height:34px;min-width:36px;padding:0 11px;border-radius:999px;
  font-size:12px;font-weight:400;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-2);
  display:grid;place-items:center;
  transition:background .3s var(--ease),color .3s var(--ease),transform .14s var(--ease);
}
.topbar button:hover{background:var(--paper-3);color:var(--ink)}
.topbar button[aria-pressed="true"]{color:var(--ink);font-weight:400}
.topbar .sep{width:1px;height:18px;background:var(--rule)}
.topbar svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.5}

/* ============================================================ layout */
.main{margin-left:var(--sidebar);min-height:100vh}
.wrap{padding:0 var(--gut)}
.section{padding-top:var(--sec);padding-bottom:var(--sec)}
.section--tight{padding-top:clamp(44px,6vw,88px);padding-bottom:clamp(44px,6vw,88px)}
.section--dark{background:var(--dark);color:var(--on-dark)}
.section--dark .eyebrow,.section--dark .mono-meta{color:var(--on-dark-2)}
.section--dark .body,.section--dark .lead{color:var(--on-dark-2)}
.section--paper2{background:var(--paper-2)}

.sec-head{
  display:grid;grid-template-columns:1fr auto;gap:20px;align-items:end;
  padding-bottom:26px;margin-bottom:38px;border-bottom:1px solid var(--rule);
}
.section--dark .sec-head{border-color:var(--rule-dark)}
.sec-head .eyebrow{margin-bottom:14px}

/* ============================================================ page head */
.pagehead{
  padding:clamp(96px,13vw,190px) var(--gut) clamp(48px,6vw,86px);
  background:var(--dark);color:var(--on-dark);
}
.pagehead .eyebrow{color:var(--on-dark-2);margin-bottom:20px}
.pagehead .lead{color:var(--on-dark-2);margin-top:26px}
.pagehead--light{background:var(--paper-2);color:var(--ink)}
.pagehead--light .eyebrow{color:var(--muted)}
.pagehead--light .lead{color:var(--ink-2)}
/* A photograph behind the title. Everything here hangs off .pagehead--photo, so a
   header without one keeps exactly the computed style it always had.
   isolation:isolate makes the header its own stacking context: the photo (-2) and
   the wash (-1) sit behind the text without the text needing to be positioned.
   The washes are graded, heaviest at the foot where the lead sits. They were
   measured 2026-09-11 on the rendered page against the brightest and the darkest
   photograph in the library, by compositing the cropped photo and the wash and
   reading the worst pixel under each line of text. The first version failed the
   eyebrow: it sits highest, where the wash is lightest, and is the smallest text.
   Hence the deeper top stop, and the eyebrow taking full-strength colour on a
   photo -- neither rule touches a header without a photo. */
.pagehead--photo{position:relative;isolation:isolate;overflow:hidden}
.pagehead-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2}
.pagehead--photo::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:var(--ph-wash,1);          /* the F-10 switch — see below */
  background:linear-gradient(to top,
    rgba(24,19,14,.82) 0%, rgba(24,19,14,.7) 60%, rgba(24,19,14,.54) 100%);
}
.pagehead--light.pagehead--photo::before{
  background:linear-gradient(to top,
    rgba(239,233,223,.95) 0%, rgba(239,233,223,.88) 60%, rgba(239,233,223,.78) 100%);
}
.pagehead--photo .eyebrow,.pagehead--photo .lead{color:var(--on-dark)}
.pagehead--light.pagehead--photo .eyebrow,.pagehead--light.pagehead--photo .lead{color:var(--ink-2)}

/* ------------------------------------------------- F-10 · bare header photo
   A trial, on the owner's instruction (2026-09-24): show the header photograph
   with no wash over it. Everything above is the measured original and is left
   untouched; this is one switch, `--ph-wash`, read by the ::before opacity.

     1  the measured wash (the original, and the default everywhere)
     0  no wash: the photograph bare, text straight on it

   ONE LINE CHANGES EVERYTHING:
     · revert entirely      — delete the rule below
     · desktop as well      — move `--ph-wash:0` out of the media query, into
                              the `:root` block at the top of this file
   The five pages with a header photo are Malarstwo, Prace na papierze,
   Obiekty, Wystawy and Kontakt; the other five have none and never change.
   WHY IT IS A TRIAL: the wash was sized by measurement in 2026-09-11, and
   without it white text over these photographs measures about 1.5:1 where the
   site holds every line to 4.5:1. Judge it on the phone before it goes live. */
@media (max-width:1024px){
  :root{--ph-wash:0}
}

/* ============================================================ hero */
.hero{position:relative;height:100vh;min-height:560px;overflow:hidden;background:var(--paper-3)}

/* Four rooms stacked in one stage, crossfaded. Only .is-on is visible; the rest
   also carry [inert], so their contents stay out of the tab order. */
.hero-stage{position:absolute;inset:0}
.hero-slide{
  position:absolute;inset:0;opacity:0;
  transition:opacity 1.8s var(--ease);
}
.hero-slide.is-on{opacity:1}

/* The photographs are shown whole and never cropped: object-fit:contain fits
   each one inside the hero on the page's paper colour, so a portrait gets
   bands at the sides rather than losing its top and bottom. They do not move —
   no pan, no zoom — so the only animation here is the crossfade above. */
.hero-photo{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;object-position:center;
}
.hero-dots{
  position:absolute;right:var(--gut);top:50%;transform:translateY(-50%);z-index:3;
  display:flex;flex-direction:column;gap:12px;
}
.hero-dot{
  width:8px;height:8px;padding:0;border:1px solid rgba(255,255,255,.75);border-radius:50%;
  background:transparent;cursor:pointer;transition:background .4s var(--ease),transform .4s var(--ease);
}
.hero-dot.is-on{background:#fff;transform:scale(1.35)}
.hero-dot:hover{background:rgba(255,255,255,.6)}

/* A wash confined to the lower left, so the headline reads without flattening
   the photograph. It has to carry more weight than it did over the drawn
   rooms: a contained photograph leaves paper-coloured bands, and white type on
   bare paper is unreadable, so the wash — not the image — has to guarantee the
   contrast under the headline whatever the photograph happens to be. */
.hero::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:
    radial-gradient(125% 82% at 0% 100%, rgba(24,19,14,.88) 0%, rgba(24,19,14,.58) 40%, rgba(24,19,14,0) 74%),
    linear-gradient(to top, rgba(24,19,14,.40) 0%, rgba(24,19,14,0) 36%);
}
.hero-inner{
  position:relative;z-index:2;height:100%;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:0 var(--gut) clamp(84px,13vh,150px);color:#fff;
}
.hero h1{
  font-size:clamp(40px,7.6vw,104px);line-height:.98;font-weight:200;letter-spacing:-.025em;
  text-shadow:0 2px 40px rgba(20,16,12,.4);
}
.hero .eyebrow{color:rgba(255,255,255,.82);margin-bottom:22px}
.hero .hero-sub{
  margin-top:24px;max-width:44ch;color:rgba(255,255,255,.9);
  font-size:clamp(15px,1.4vw,19px);text-shadow:0 1px 24px rgba(20,16,12,.5);
}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:38px}
.scroll-hint{
  position:absolute;left:var(--gut);bottom:34px;z-index:2;
  font-size:11px;font-weight:400;letter-spacing:.20em;text-transform:uppercase;color:rgba(255,255,255,.78);
  display:flex;align-items:center;gap:10px;
}
.scroll-hint i{display:block;width:44px;height:1px;background:rgba(255,255,255,.6);transform-origin:left;animation:pull 2.6s var(--ease) infinite}
@keyframes pull{0%,100%{transform:scaleX(.35)}50%{transform:scaleX(1)}}

/* ============================================================ buttons */
.btn{
  display:inline-flex;align-items:center;gap:12px;
  padding:14px 26px;border:1px solid var(--ink);
  font-size:12px;font-weight:400;letter-spacing:.16em;text-transform:uppercase;
  transition:background .4s var(--ease),color .4s var(--ease),border-color .4s var(--ease),
             transform .14s var(--ease);
}
.btn:hover{background:var(--ink);color:var(--paper)}
.btn--solid{background:var(--ink);color:var(--paper)}
.btn--solid:hover{background:var(--clay);border-color:var(--clay);color:#fff}
.btn--light{border-color:rgba(255,255,255,.7);color:#fff}
.btn--light:hover{background:#fff;color:var(--ink);border-color:#fff}
.btn--onDark{border-color:var(--rule-dark);color:var(--on-dark)}
.btn--onDark:hover{background:var(--on-dark);color:var(--dark)}

.arrow{
  display:inline-flex;align-items:center;gap:11px;
  font-size:12px;font-weight:400;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);
}
/* fixed box, scaled rule: composited, and the label no longer shifts on hover */
.arrow i{
  display:block;width:44px;height:1px;background:currentColor;
  transform:scaleX(.59);transform-origin:left;
  transition:transform .4s var(--ease);
}
.arrow:hover i{transform:scaleX(1)}
.section--dark .arrow,.foot .arrow{color:var(--on-dark)}

/* ============================================================ filter bar */
.filterbar{
  position:sticky;top:0;z-index:40;
  background:color-mix(in srgb,var(--paper) 86%,transparent);
  backdrop-filter:saturate(180%) blur(14px);
  border-bottom:1px solid var(--rule);
}
.filterbar-in{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 30px;
  padding:16px var(--gut);
}
.tabs{display:flex;gap:4px;flex-wrap:wrap}
.tab{
  position:relative;padding:9px 4px;margin-right:22px;
  font-size:13.5px;font-weight:400;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);
  transition:color .3s var(--ease),transform .14s var(--ease);
}
.tab::after{
  content:"";position:absolute;left:0;right:0;bottom:2px;height:1px;background:var(--ink);
  transform:scaleX(0);transform-origin:center;transition:transform .4s var(--ease);
}
.tab:hover{color:var(--ink)}
.tab[aria-pressed="true"]{color:var(--ink)}
.tab[aria-pressed="true"]::after{transform:scaleX(1)}
.tab .n{font-size:11px;vertical-align:super;margin-left:3px;color:var(--muted)}

.chips{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}
.chip{
  padding:7px 15px;border:1px solid var(--rule);border-radius:999px;
  font-size:12px;font-weight:400;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-2);
  transition:border-color .3s var(--ease),background .3s var(--ease),color .3s var(--ease),
             transform .14s var(--ease);
}
.chip:hover{border-color:var(--ink)}
.chip[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--paper)}

/* Press feedback. The stylesheet carried 36 :hover rules and no :active at all, so a
   tap on touch — where there is no hover to begin with — got no acknowledgement.
   transform only: an opacity dim reads as "disabled" on this paper palette.
   .totop and .hero-dot are deliberately excluded, both use transform for state;
   .nav-toggle too, it is a full-width text row. */
.btn:active,.btn-news:active,.tab:active,.chip:active,
.topbar button:active,.modal-close:active,.burger:active,
button[data-close]:active{transform:scale(.97)}

.result-count{font-size:12px;font-weight:400;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);padding:0 var(--gut);margin-top:26px}

/* ============================================================ work grid */
.grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(34px,4.4vw,76px) clamp(22px,2.8vw,46px);
  align-items:start;
}
/* .grid--2 removed 2026-09-26 with the Kontakt page's two-block band, its only
   user. The 680 px breakpoint's copy went with it. */

.tile{position:relative;text-align:left;width:100%;display:block}
/* One well shape for every work, whatever its proportions, with the painting
   scaled to fit whole inside it — the same 4/5 the cycle and series cards use.
   The wells used to take each painting's own aspect-ratio (stamped inline by
   build.py), which left tile heights running 158px to 675px in one grid: a
   tall canvas overflowed a laptop viewport while a panorama read as a strip.
   Do not put the inline aspect-ratio back without also dropping this rule —
   an inline style wins and the grid goes ragged again. */
/* The well is deliberately UNPAINTED. It still reserves the 4/5 box that keeps
   every tile the same height, but a work narrower or wider than 4/5 leaves page
   background rather than a visible band. Giving this a background of its own
   (--paper-3, as it once had) is what draws the "side bars" — don't. */
.tile .shot{
  position:relative;overflow:hidden;background:transparent;
  display:block;aspect-ratio:4/5;
}
.tile .shot img{
  width:100%;height:100%;object-fit:contain;object-position:bottom;
  transition:transform 1.1s var(--ease),filter .6s var(--ease);
}
/* Hover tints the PAINTING, not the box: an inset overlay would paint the whole
   4/5 area and expose the very rectangle the transparent well hides. And there
   is no scale here on purpose — the image is fitted to the box, so any zoom
   crops its edges, which is the one thing this grid exists to avoid. The other
   cards (.cycle-shot) still zoom; they use object-fit:cover. */
.tile:hover .shot img{filter:brightness(.93)}
.tile .zoom{
  position:absolute;right:14px;bottom:14px;z-index:2;
  width:38px;height:38px;border-radius:50%;background:rgba(246,242,235,.94);
  display:grid;place-items:center;
  opacity:0;transform:translateY(8px) scale(.9);
  transition:opacity .45s var(--ease),transform .45s var(--ease);
}
.tile:hover .zoom{opacity:1;transform:none}
.tile .zoom svg{width:15px;height:15px;stroke:var(--ink);fill:none;stroke-width:1.5}

.tile-cap{display:flex;padding-top:16px;justify-content:space-between;gap:14px;align-items:baseline}
.tile-cap .t{font-size:16.5px;font-weight:500;letter-spacing:-.005em}
.tile-cap .y{font-size:13.5px;font-weight:400;color:var(--muted);white-space:nowrap}
.tile-sub{display:block;margin-top:6px;font-size:14.5px;font-weight:400;color:var(--ink-2);line-height:1.55}

.status{
  display:inline-flex;align-items:center;gap:6px;margin-top:9px;clear:both;
  font-size:11.5px;font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.status i{width:5px;height:5px;border-radius:50%;background:var(--muted);display:block}
.status--available{color:var(--clay)}
.status--available i{background:var(--clay)}

/* ============================================================ split */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,5vw,90px);align-items:center}
.split--40{grid-template-columns:.8fr 1.2fr}
.stack>*+*{margin-top:22px}
.stack-lg>*+*{margin-top:38px}

/* ============================================================ exhibitions */
.exh{border-top:1px solid var(--rule)}
.exh-row{
  display:grid;
  grid-template-columns:92px minmax(180px,1fr) minmax(200px,1.15fr) minmax(260px,1.5fr);
  gap:clamp(16px,2.6vw,40px);
  padding:34px 0;border-bottom:1px solid var(--rule);align-items:start;
  transition:background .4s var(--ease);
}
.exh-row:hover{background:var(--paper-2)}
.exh-year{font-size:14px;letter-spacing:.13em;color:var(--muted);padding-top:5px}
.exh-shot{width:100%;aspect-ratio:16/10;overflow:hidden;background:var(--paper-3)}
.exh-shot img{width:100%;height:100%;object-fit:cover;transition:transform 1.1s var(--ease)}
.exh-row:hover .exh-shot img{transform:scale(1.05)}
.exh-badge{
  display:inline-block;padding:5px 12px;border:1px solid var(--rule);border-radius:999px;
  font-size:11.5px;font-weight:400;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.exh-badge--now{border-color:var(--clay);color:var(--clay)}
.exh-badge--next{border-color:var(--ink);color:var(--ink)}

/* ============================================================ contact */
.form{display:grid;gap:20px;max-width:560px;justify-items:start}
.form>.field{width:100%}
.form>.btn{justify-self:start}
.field label{
  display:block;margin-bottom:8px;
  font-size:11.5px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
}
.field input,.field textarea,.field select{
  width:100%;padding:13px 0;background:transparent;
  border:0;border-bottom:1px solid var(--rule);
  font-size:15px;font-weight:300;transition:border-color .35s var(--ease);
}
.field input:focus,.field textarea:focus,.field select:focus{outline:none;border-bottom-color:var(--ink)}
.field textarea{resize:vertical;min-height:112px}
.field.has-error input,.field.has-error textarea{border-bottom-color:#A33}
/* consent tickbox — the label styling above is for a field caption, so almost
   all of it has to be undone here, including the sizing on .field input */
.field--consent{margin-top:2px}
.field .consent{
  display:grid;grid-template-columns:auto 1fr;gap:12px;align-items:start;
  margin-bottom:0;cursor:pointer;text-transform:none;letter-spacing:0;
}
.field .consent input[type="checkbox"]{
  width:16px;height:16px;margin:3px 0 0;padding:0;border:0;
  accent-color:var(--clay);cursor:pointer;
}
.field .consent span{
  font-size:12.5px;font-weight:300;line-height:1.62;color:var(--ink-2);
  letter-spacing:0;text-transform:none;
}
.field .consent a{text-decoration:underline;text-underline-offset:2px}
.field .consent a:hover{color:var(--clay)}
/* mark the control and say why; recolouring the whole sentence only makes the
   thing the reader now has to read harder to read */
.field--consent.has-error input[type="checkbox"]{outline:2px solid #A33;outline-offset:3px}

.err{display:none;margin-top:7px;font-size:11.5px;color:#A33;letter-spacing:.04em}
.field.has-error .err{display:block}
.form-note{font-size:12px;color:var(--muted);max-width:52ch;line-height:1.6}
/* The one rare, positive moment on the site, so it gets a slightly longer beat than the
   UI band. display can only be transitioned with allow-discrete, and the entry needs
   @starting-style to have somewhere to animate from; without support for either the box
   just appears, which is what it did before. */
.form-ok{
  display:none;padding:18px 20px;background:var(--paper-2);border-left:2px solid var(--clay);
  font-size:14px;color:var(--ink-2);
  opacity:0;transform:translateY(8px);
  transition:opacity .26s var(--ease),transform .26s var(--ease),display .26s allow-discrete;
}
.form-ok.is-on{display:block;opacity:1;transform:none}
@starting-style{
  .form-ok.is-on{opacity:0;transform:translateY(8px)}
}

.info-list div{padding:15px 0;border-bottom:1px solid var(--rule);display:grid;grid-template-columns:110px 1fr;gap:18px}
.info-list dt{font-size:11.5px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);padding-top:3px}
.info-list dd{font-size:15px;color:var(--ink-2)}
.info-list a:hover{color:var(--clay)}
.section--dark .info-list div{border-color:var(--rule-dark)}
.section--dark .info-list dt{color:var(--on-dark-2)}
.section--dark .info-list dd{color:var(--on-dark)}
.section--dark .info-list a:hover{color:#fff}


/* ============================================================ search */
.search{
  position:fixed;inset:0;z-index:180;display:none;
  background:color-mix(in srgb,var(--paper) 97%,transparent);backdrop-filter:blur(18px);
}
.search.is-on{display:block}
.search-in{max-width:820px;margin:0 auto;padding:clamp(60px,10vh,140px) var(--gut) 40px}
.search-field{display:flex;align-items:center;gap:16px;border-bottom:1px solid var(--ink);padding-bottom:14px}
.search-field input{
  flex:1;border:0;background:transparent;font-size:clamp(22px,3.4vw,38px);font-weight:200;
  letter-spacing:-.01em;padding:6px 0;
}
.search-field input:focus{outline:none}
.search-field input::-webkit-search-cancel-button,
.search-field input::-webkit-search-decoration{-webkit-appearance:none;appearance:none;display:none}
.search-field svg{width:22px;height:22px;stroke:var(--muted);fill:none;stroke-width:1.5}
.search-hint{margin-top:16px;font-size:12px;font-weight:400;letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
.search-results{margin-top:34px;max-height:52vh;overflow-y:auto}
.search-results a{
  display:grid;grid-template-columns:56px 1fr auto;gap:18px;align-items:center;
  padding:13px 8px;border-bottom:1px solid var(--rule-2);transition:background .25s var(--ease);
}
.search-results a:hover,.search-results a.is-cur{background:var(--paper-2)}
.search-results .thumb{width:56px;height:44px;object-fit:cover;background:var(--paper-3)}
.search-results .t{font-size:15px}
.search-results .k{font-size:11px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted)}

/* ============================================================ modal */
/* The scrim and the panel are animated here, in CSS, rather than in openDialog/
   closeDialog — those are shared with the search overlay, which is opened with ⌘K and
   must stay instant. Scoping to .modal keeps the two apart by construction.
   Entry 200ms / exit 160ms: the shorter timing lives on the base rule, which is what
   applies when .is-on is removed. Centered, so no transform-origin. */
.modal{
  position:fixed;inset:0;z-index:190;display:none;place-items:center;
  background:rgba(20,17,13,.6);padding:24px;
  opacity:0;
  transition:opacity .16s var(--ease),display .16s allow-discrete;
}
.modal.is-on{
  display:grid;opacity:1;
  transition:opacity .2s var(--ease),display .2s allow-discrete;
}
.modal-box{
  background:var(--paper);max-width:460px;width:100%;padding:clamp(28px,4vw,44px);
  position:relative;
  opacity:0;transform:scale(.97);
  transition:opacity .16s var(--ease),transform .16s var(--ease);
}
.modal.is-on .modal-box{
  opacity:1;transform:none;
  transition:opacity .2s var(--ease),transform .2s var(--ease);
}
@starting-style{
  .modal.is-on{opacity:0}
  .modal.is-on .modal-box{opacity:0;transform:scale(.97)}
}
.modal-close{
  position:absolute;top:14px;right:14px;width:34px;height:34px;display:grid;place-items:center;
  transition:transform .14s var(--ease);
}
.modal-close svg{width:15px;height:15px;stroke:var(--ink-2);fill:none;stroke-width:1.5}

/* ============================================================ to top */
.totop{
  position:fixed;right:24px;bottom:24px;z-index:80;
  width:44px;height:44px;border:1px solid var(--rule);background:var(--paper);
  display:grid;place-items:center;
  opacity:0;pointer-events:none;transform:translateY(10px);
  transition:opacity .4s var(--ease),transform .4s var(--ease),background .3s var(--ease);
}
.totop.is-on{opacity:1;pointer-events:auto;transform:none}
.totop:hover{background:var(--ink)}
.totop:hover svg{stroke:var(--paper)}
.totop svg{width:15px;height:15px;stroke:var(--ink);fill:none;stroke-width:1.5;transition:stroke .3s var(--ease)}

/* ======================================================= not found (404) */
/* The recovery routes. Built from the same rule + hover-shifted chevron the
   rest of the site uses, so the page reads as part of it rather than as an
   error screen the server threw up. */
.nf-list{list-style:none;max-width:44ch;border-top:1px solid var(--rule)}
.nf-link{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:19px 2px;border-bottom:1px solid var(--rule);
  font-size:16.5px;color:var(--ink-2);
  transition:color .3s var(--ease),padding-left .3s var(--ease);
}
.nf-link svg{
  width:17px;height:17px;flex:none;stroke:currentColor;stroke-width:1.4;
  fill:none;opacity:.4;transition:transform .3s var(--ease),opacity .3s var(--ease);
}
.nf-link:hover{color:var(--clay);padding-left:8px}
.nf-link:hover svg{transform:translateX(4px);opacity:1}

/* ================================================= analytics consent bar */
/* Pinned to the bottom rather than covering the page: this is a question, not a
   wall, and the site is fully usable while it is unanswered. Both buttons are
   the same size and sit side by side -- the GDPR requires refusing to be as easy
   as accepting, and a greyed-out "reject" is the usual way that rule is broken. */
.cookiebar{
  position:fixed;left:0;right:0;bottom:0;z-index:70;
  background:var(--dark);color:var(--on-dark);
  border-top:1px solid var(--rule-dark);
  animation:cookiebar-in .5s var(--ease) both;
}
.cookiebar-in{
  max-width:1100px;margin:0 auto;padding:20px var(--gut);
  display:grid;grid-template-columns:1fr auto;gap:8px 32px;align-items:center;
}
.cookiebar-h{
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--on-dark);margin-bottom:8px;
}
.cookiebar-b{font-size:14.5px;line-height:1.6;color:var(--on-dark-2);max-width:66ch}
.cookiebar-actions{display:flex;gap:12px;flex-wrap:wrap}
.cookiebar-actions .btn{white-space:nowrap}
.cookiebar-actions .btn:not(.btn--solid){
  border-color:var(--rule-dark);color:var(--on-dark);
}
.cookiebar-actions .btn:not(.btn--solid):hover{background:var(--on-dark);color:var(--dark)}
.cookiebar-more{grid-column:1/-1;font-size:12.5px;color:var(--on-dark-2);margin-top:4px}
.cookiebar-more a{color:var(--on-dark-2);text-decoration:underline;text-underline-offset:3px}
.cookiebar-more a:hover{color:var(--on-dark)}
@keyframes cookiebar-in{from{transform:translateY(100%);opacity:0}to{transform:none;opacity:1}}
@media (max-width:680px){
  .cookiebar-in{grid-template-columns:1fr;gap:14px;padding:18px var(--gut)}
  .cookiebar-actions .btn{flex:1 1 auto;text-align:center}
}
@media (prefers-reduced-motion:reduce){
  .cookiebar{animation:none}
}

/* ============================================================ footer */
.foot{background:var(--dark);color:var(--on-dark-2);padding:clamp(48px,6vw,84px) var(--gut) 36px}
.foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:clamp(24px,4vw,60px)}
.foot h3{color:var(--on-dark);margin-bottom:16px;font-size:12px;letter-spacing:.18em;text-transform:uppercase;font-weight:500}
.foot a{transition:color .3s var(--ease)}
.foot a:hover{color:var(--on-dark)}
.foot li+li{margin-top:9px}
.foot .fine{
  margin-top:48px;padding-top:22px;border-top:1px solid var(--rule-dark);
  display:flex;flex-wrap:wrap;gap:14px 28px;justify-content:space-between;
  font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
}

/* ============================================================ mobile nav */
.burger{display:none}
.drawer-scrim{display:none}

/* ============================================================ reveal */
.rv{opacity:0;transform:translateY(22px);transition:opacity .9s var(--ease),transform .9s var(--ease)}
.rv.is-in{opacity:1;transform:none}
.rv-d1{transition-delay:.08s}

/* ============================================================ work page */
.workpage{padding-top:clamp(88px,10vw,132px);padding-bottom:var(--sec)}
.work-back{margin-bottom:clamp(26px,3vw,44px)}
.work-back a{
  display:inline-flex;align-items:center;gap:10px;
  font-size:12px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
  transition:color .3s var(--ease);
}
.work-back a:hover{color:var(--ink)}
.work-back svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.5}

.work-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,84px);align-items:start}
.work-figure{position:sticky;top:34px;margin:0}
.work-figure img{width:100%;background:var(--paper-3)}
.work-figure figcaption{margin-top:14px;max-width:46ch;line-height:1.6}

.work-artist{font-size:13px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);margin-bottom:16px}
.work-artist a{transition:color .3s var(--ease)}
.work-artist a:hover{color:var(--clay)}
.work-sub{margin-top:14px;font-size:15px;color:var(--ink-2)}

.work-spec{
  margin-top:clamp(26px,3vw,38px);
  padding-left:clamp(18px,2vw,26px);border-left:2px solid var(--clay);
}
.work-medium{font-size:16.5px;color:var(--ink)}
.work-dl{margin-top:16px}
.work-dl div{display:flex;gap:16px;padding:4px 0;font-size:14px}
.work-dl dt{color:var(--muted);min-width:clamp(120px,13vw,170px)}
.work-dl dd{color:var(--ink-2)}
.work-status{margin-top:22px;font-size:16px;color:var(--muted)}
.work-status--on{color:var(--clay)}
.work-price{margin-top:4px;font-size:19px;font-weight:400}
.work-price--muted{font-size:15px;font-weight:300;color:var(--muted)}
.work-colour{
  margin-top:18px;font-size:14px;line-height:1.65;color:var(--muted);
  max-width:54ch;font-style:italic;
}

.inquire{margin-top:clamp(30px,3.4vw,46px)}
.inquire-h{
  display:flex;align-items:center;gap:11px;
  font-size:13px;letter-spacing:.15em;text-transform:uppercase;
  font-weight:500;color:var(--clay);
}
.inquire-h svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.4;flex:none}
.inquire .body{margin-top:14px;font-size:14.5px}

.work-cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(30px,3.4vw,44px)}

.work-nav{
  display:grid;grid-template-columns:1fr auto 1fr;gap:20px;align-items:start;
  margin-top:clamp(48px,6vw,92px);padding-top:26px;border-top:1px solid var(--rule);
}
.wnav{
  font-size:11px;font-weight:400;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
  transition:color .3s var(--ease);
}
.wnav:hover{color:var(--ink)}
.wnav--next{text-align:right}
.wnav--all{justify-self:center;align-self:center}
.wnav-t{display:block;margin-top:6px;font-size:14.5px;letter-spacing:0;text-transform:none;color:var(--ink)}

/* ============================================================ artist statement */
.statement{padding:clamp(60px,7vh,100px) 0 clamp(48px,6vh,88px)}
.statement-head{margin-bottom:clamp(34px,4vh,62px)}
.statement-head .eyebrow{margin-bottom:22px}
.statement-lead{
  font-size:clamp(30px,4.6vw,62px);line-height:1.1;font-weight:200;letter-spacing:-.02em;
  max-width:19ch;
}
.statement-p{
  max-width:52ch;font-size:clamp(16px,1.3vw,18.5px);line-height:1.75;color:var(--ink-2);
}
.statement-p + .statement-p{margin-top:clamp(20px,2.4vh,30px)}
.statement-foot{margin-top:clamp(36px,5vh,72px)}

/* alternating rows; the painting bleeds off the outer edge, the text keeps the gutter */
.st-row{
  display:grid;grid-template-columns:1.12fr .88fr;
  gap:clamp(26px,4vw,72px);align-items:center;
  margin:clamp(40px,5.5vh,88px) 0;
}
.st-row--iright{padding-left:var(--gut)}
.st-row--ileft{padding-right:var(--gut)}
.st-row--ileft .st-figure{order:-1}
.st-text{max-width:52ch}
.st-figure{margin:0}
.st-figure a{display:block;overflow:hidden;background:var(--paper-3)}
.st-figure img{
  width:100%;height:auto;display:block;
  transition:transform 1.1s var(--ease);
}
.st-figure a:hover img{transform:scale(1.03)}
.st-figure figcaption{margin-top:14px}
.st-row--ileft .st-figure figcaption{padding-left:var(--gut)}
.st-row--iright .st-figure figcaption{padding-right:var(--gut)}

/* full-width black band, a fifth of the viewport tall, carrying one line */
.st-band{
  background:var(--dark);color:var(--on-dark);
  min-height:20vh;display:flex;align-items:center;
  padding:clamp(22px,2.6vh,40px) var(--gut);
  margin:clamp(46px,7vh,104px) 0;
}
.st-band blockquote{
  margin:0;max-width:34ch;
  font-size:clamp(19px,2.4vw,34px);line-height:1.22;font-weight:200;letter-spacing:-.012em;
}

/* ============================================================ cycles page */
.cycle-list{display:grid;gap:clamp(56px,8vw,120px)}
.cycle-row{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4.5vw,80px);align-items:center}
.cycle-row:nth-child(even) .cycle-shot{order:2}
.cycle-shot{display:block;overflow:hidden;background:var(--paper-3);aspect-ratio:4/5}
.cycle-shot img{width:100%;height:100%;object-fit:cover;transition:transform 1.2s var(--ease)}
.cycle-row:hover .cycle-shot img{transform:scale(1.05)}
.cycle-info .d2{margin:8px 0 18px}
.cycle-info .d2 a{transition:color .3s var(--ease)}
.cycle-info .d2 a:hover{color:var(--clay)}
.cycle-info p+p{margin-top:18px}

/* ============================================================ catalogue type
   The catalogue reads one step larger than the rest of the site: body copy at
   18px rather than 16px, everything else scaled from it by the same 1.125.
   `data-cat` is set on <html> by build.py for the three work grids and every
   work page — see the note there.

   Scaled: running copy and the values a reader actually reads (medium, size,
   price, notes). NOT scaled: uppercase tracked labels, tabs, chips, nav,
   eyebrows and display headings — raising those would make it a type-scale
   change rather than a body-text change, and the point was to move one thing. */
html[data-cat] body{font-size:18px}

html[data-cat] .lead{font-size:clamp(19.1px,1.74vw,23.6px)}

html[data-cat] .tile-cap .t{font-size:18.6px}
html[data-cat] .tile-cap .y{font-size:15.2px}
/* at this size the medium line wraps in a 3-up grid and strands the unit
   ("… 140 × 100" / "cm"); pretty pulls a word down rather than leaving one */
html[data-cat] .tile-sub{font-size:16.3px;text-wrap:pretty}

html[data-cat] .work-sub{font-size:16.9px}
html[data-cat] .work-medium{font-size:18.6px}
html[data-cat] .work-dl div{font-size:15.8px}
html[data-cat] .work-status{font-size:18px}
html[data-cat] .work-price{font-size:21.4px}
html[data-cat] .work-price--muted{font-size:16.9px}
/* the sentence under each painting is prose, not metadata — it happens to be
   marked .mono-meta, and it is the only .mono-meta on a work page, so scoping
   it to the figure caption scales it without touching the label style anywhere else */
html[data-cat] .work-figure figcaption{font-size:15.8px}
html[data-cat] .work-colour{font-size:15.8px}
html[data-cat] .inquire .body{font-size:16.3px}
html[data-cat] .wnav-t{font-size:16.3px}

/* ============================================================ responsive */
@media (max-width:1180px){
  /* stack meta, text and image in one column beside the year */
  .exh-row{grid-template-columns:88px 1fr;gap:18px clamp(16px,3vw,32px)}
  .exh-row>*:not(.exh-year){grid-column:2}
}
@media (max-width:1024px){
  :root{--sidebar:0px;--bar-strip:68px}
  .sidebar{
    inset:0 auto 0 0;width:min(320px,84vw);padding-top:88px;
    transform:translateX(-102%);transition:transform .5s var(--ease);
    box-shadow:0 0 60px rgba(20,16,12,.16);
  }
  body.nav-open .sidebar{transform:none}
  .drawer-scrim{
    display:block;position:fixed;inset:0;z-index:55;background:rgba(20,17,13,.45);
    opacity:0;pointer-events:none;transition:opacity .4s var(--ease);
  }
  body.nav-open .drawer-scrim{opacity:1;pointer-events:auto}
  .main{margin-left:0}
  .burger{
    display:grid;position:fixed;top:22px;left:22px;z-index:70;
    width:46px;height:46px;place-items:center;
    background:var(--paper);border:1px solid var(--rule);border-radius:999px;
    transition:transform .14s var(--ease);
  }
  .burger i{display:block;width:17px;height:1px;background:var(--ink);position:relative;transition:background .2s}
  .burger i::before,.burger i::after{
    content:"";position:absolute;left:0;width:17px;height:1px;background:var(--ink);
    transition:transform .35s var(--ease);
  }
  .burger i::before{top:-5px}
  .burger i::after{top:5px}
  body.nav-open .burger i{background:transparent}
  body.nav-open .burger i::before{transform:translateY(5px) rotate(45deg)}
  body.nav-open .burger i::after{transform:translateY(-5px) rotate(-45deg)}
  .grid{grid-template-columns:repeat(2,1fr)}
  .work-grid{grid-template-columns:1fr;gap:34px}
  .work-figure{position:static}
  .work-figure img{max-width:560px}
  .split,.split--40{grid-template-columns:1fr}
  .cycle-row{grid-template-columns:1fr;gap:22px}
  .st-row{grid-template-columns:1fr;gap:24px;padding:0 var(--gut);margin:clamp(44px,6vh,80px) 0}
  .st-row--ileft .st-figure{order:0}
  .st-row--ileft .st-figure figcaption,
  .st-row--iright .st-figure figcaption{padding:0}
  .st-figure img{max-height:74vh;width:auto;max-width:100%}
  .st-band{min-height:24vh}
  .cycle-row:nth-child(even) .cycle-shot{order:0}
  /* F-10: the cycle cover in its own shape, not cropped to a band. It was
     16/10 with object-fit:cover, which cut the top and bottom off a tall
     painting — the one thing a catalogue must not do. The intrinsic size is
     on the <img> (build.py), so the row still reserves its space before the
     photo loads. Desktop keeps the uniform 4/5 well. */
  .cycle-shot{aspect-ratio:auto}
  .cycle-shot img{height:auto;object-fit:contain}
  /* The same for the exhibition photographs, which were cropped to 16/10 and
     to 16/9 below 680 px. Scoped to .exh-row, because the wallpaper card
     borrows .exh-shot and sets its own 7/5 inline. */
  .exh-row .exh-shot{aspect-ratio:auto}
  .exh-row .exh-shot img{height:auto;object-fit:contain}
  .foot-grid{grid-template-columns:1fr 1fr}

  /* Home banner. A landscape photograph is far shorter than a phone's banner
     (205–369 px of 714), so centring it left an empty paper band on top with
     the round menu and search buttons floating on it. The photograph now hangs
     from the top edge — still whole, never cropped — and the space it leaves
     below is the dark ground the name and buttons stand on. */
  .hero{background:var(--dark)}
  .hero-photo{object-position:top center}

  /* Filter bar. Sticky, it wrapped to ~200 px on a phone, covered the artwork
     and slid under the round buttons. Here it scrolls away with the page and
     site.js (initFilterbar) brings it back, pinned, when the reader scrolls up.
     Pinned, it carries a strip on top that clears the round buttons (22 px
     offset + 46 px button); the strip is padding cancelled by an equal negative
     margin, so pinning never moves the page underneath. */
  .filterbar{position:relative;transition:transform .45s var(--ease)}
  .filterbar.is-pinned{
    position:sticky;top:0;
    padding-top:var(--bar-strip);margin-top:calc(-1 * var(--bar-strip));
  }
  .filterbar.is-hidden{transform:translateY(-100%)}
  .filterbar.no-anim{transition:none}
}
@media (max-width:680px){
  body{font-size:15.5px}
  /* the catalogue keeps its +1.125 step here too — without restating it the
     scoped rule above out-specifies this one and phones stay at the desktop
     size, which is the opposite of what this breakpoint is for */
  html[data-cat] body{font-size:17.4px}
  .grid{grid-template-columns:1fr;gap:36px}
  .sec-head{grid-template-columns:1fr}
  .exh-row{grid-template-columns:1fr;gap:14px}
  /* (the 16/9 crop that stood here is gone — F-10 shows these whole) */
  .foot-grid{grid-template-columns:1fr}
  .filterbar-in{gap:6px 16px}
  .chips{margin-left:0;width:100%}
  .tab{margin-right:16px;font-size:12.5px}
  .topbar{top:22px;right:16px}
  /* Phones — the owner's design (F-11, 2026-09-25): the photograph fills the
     top 3/5 of the screen with the eyebrow, the name and the sentence on it
     under a light shade, and the two buttons on a black bar directly beneath,
     only as tall as they need. The photograph is the artist's own upright 4:5
     crop (statement.hero[].photo_mobile, chosen by a <source> in the markup),
     so object-fit:cover fills the 3/5 with almost nothing lost — 4 % of the
     width at 375×812. This replaces F-9's stacked banner.

     Why grid with display:contents: the text and the buttons are siblings
     inside one .hero-inner, and here they have to land in different bands.
     Making .hero-inner a pass-through turns its four children into grid items
     of .hero, so the stage can span the three text rows while .hero-cta takes
     a row of its own below. Row 1 is the only fr, so it swallows the slack and
     the text sits at the foot of the photograph whatever the phone's height. */
  .hero{
    display:grid;grid-template-columns:100%;
    grid-template-rows:1fr auto auto auto auto;
    height:auto;min-height:0;background:var(--dark);
  }
  .hero-stage{grid-area:1 / 1 / 5 / 2;position:relative;inset:auto;min-height:60vh}
  .hero-photo{object-fit:cover;object-position:center}
  .hero-inner{display:contents}
  /* grid-column:1 on every one of them is not decoration: the stage already
     occupies column 1 of rows 1–4, so auto-placement would push the text into
     an implicit second column, off the side of the screen. Placed explicitly,
     they share the cells with the photograph, which is the point. */
  .hero .eyebrow,.hero h1,.hero .hero-sub{position:relative;z-index:2;grid-column:1;padding:0 var(--gut)}
  .hero .eyebrow{grid-row:2;margin-bottom:14px}
  .hero h1{grid-row:3}
  .hero .hero-sub{grid-row:4;margin-top:16px;padding-bottom:30px}
  .hero-cta{grid-row:5;grid-column:1;position:relative;z-index:2;margin:0;padding:22px var(--gut) 26px}
  /* Full strength on the photograph, the same trade the sub-page headers make:
     the eyebrow at .82 and the lead at .9 each needed ~.07 more shade than
     plain white does, and the shade veils the painting while the text does not. */
  .hero .eyebrow,.hero .hero-sub{color:#fff}
  /* The shade. Measured on all five crops, worst pixel under every line: they
     need alpha .57 (eyebrow, name) and .53 (lead), so this is the lightest
     gradient of this shape that clears 4.5:1, plus a small margin. It is flat
     across the text and gone by 72 % up, leaving the top of the picture clear.
     Re-measure before lightening it, and after any new banner crop. TODO F-11. */
  .hero-stage::after{
    content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
    background:linear-gradient(to top,
      rgba(20,16,12,.62) 0%, rgba(20,16,12,.60) 45%, rgba(20,16,12,0) 72%);
  }
  .hero::after{display:none}          /* the desktop wash stays off here */
  .hero-dots{top:30vh}                /* centred on the photograph, not the banner */
  .scroll-hint{display:none}          /* the buttons now sit where it used to */
  .hero-dots{right:14px;gap:10px}
  .info-list div{grid-template-columns:1fr;gap:4px}
  .work-dl div{flex-direction:column;gap:2px}
  .work-nav{grid-template-columns:1fr;gap:16px;text-align:left}
  .wnav--next{text-align:left}
  .wnav--all{justify-self:start}
}

/* ============================================================ prefs */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .rv{opacity:1;transform:none}
}

@media print{
  .sidebar,.topbar,.totop,.filterbar,.burger,.foot,.hero,.search,.modal{display:none!important}
  .main{margin:0}
  body{background:#fff;font-size:11pt}
  .pagehead{background:#fff;color:#000;padding:0 0 18pt}
  .pagehead-bg,.pagehead--photo::before{display:none}
  .section{padding:12pt 0}
  a{text-decoration:none}
}

/* Honeypot: off-screen rather than display:none, because some bots skip fields
   that are display:none. Kept out of the tab order and the accessibility tree
   by tabindex="-1" and aria-hidden on the wrapper, so a real visitor — including
   one using a screen reader — never meets it. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* Shown only when the enquiry endpoint could not be reached and the form has
   fallen back to the visitor's mail client. */
.form-fallback{display:none;margin-top:14px;color:var(--muted);font-size:14px}
.form-fallback.is-on{display:block}
