/* ============================================================
   ALINA SZAPOCZNIKOW — Expositions index : Liste + Galerie
   Loaded on index.html, expositions.html, actualites.html, collections.html and
   publications.html: the .xlist / .xfiche kit and the one .xgalerie are shared. Replaced the
   old Grille/Liste split (the .exh-toolbar / .exh-grid path in wireframe.css,
   since retired). Origin: the prototype in
   _prototypes/expositions-index/, itself built from the reference in
   _references/expositions index prototype/. Engine: expo-index.js.

   LISTE   = archivio-uno row rollover   (grid-template-rows 0fr → 1fr, pure CSS), the preview
             floating over the rows below since v110 (meeting 1 Oct: the list never moves)
   GALERIE = one grid on every page since 04.10 (.xgalerie, below): each item's image entière
   FICHE   = bespoke side panel (header · title · dates over image | fields+desc),
             overlapping the index at 85% (NOT the shared fiche.js — it stacks the
             image as a full-width hero, unreadable at this width).

   The toolbar sticks UNDER the site topbar (var(--topbar-h) from tweaks-apply.js).

   ⚠ CLASS NAMESPACING — do not remove. wireframe.css already owns
   .reveal .row .yr .hide .on .note .meta; `.reveal{opacity:0}` is only
   lifted by the reveal-on-scroll observer, so anything reusing that name
   lays out and paints nothing. Everything here is prefixed x*.
   ============================================================ */

.xsheet { padding: 0 var(--xedge, 10px); --xedge: 10px; }

/* ONE image scale for every list reveal. Sizing method (shared by all four lists):
   fix the HEIGHT, let width:auto + object-fit:contain keep the true aspect ratio —
   the archive mixes portrait sculpture shots with landscape installation views, so a
   common height gives a tidy baseline without ever cropping. Source is M_ (815px) in
   every case, so 240px is well within resolution. Change the scale here, once. */
:root { --xthumb: 240px; }


/* ---- THE PAGE'S BAR (Seba 04.10, after Mousse Magazine): the page's title on the left, its tools
   on the right (Liste/Galerie; the order; the type of actualité), under the site's bar. Until
   04.10 the tools sat IN the site's bar beside the menu and FR/EN, which broke its row and sent
   the menu behind its button on a desktop. Sticky at --bar-under (wireframe.css): under the site's
   bar, and at the top while the site's bar has slid away on scrolling down (tweaks-apply.js). The
   look of the home's section bars (home.css .hz-down). On Collections and Publications it holds
   their Liste / Galerie (.pubview). The Chronologie keeps its bar floating over its strip, so it has
   none (Seba 04.10). ---- */
.xpagebar { position: sticky; top: var(--bar-under, 53px); z-index: 35;
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 24px;
  padding: 13px 10px; background: color-mix(in srgb, var(--bg) 45%, #fff);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  transition: top .4s cubic-bezier(.19, 1, .22, 1); }
.xpage-t { margin: 0; font-family: var(--display); font-weight: 400; font-size: 0.95rem; line-height: inherit; color: var(--ink); }
.xpagebar .pubview { margin: 0; }
@media (prefers-reduced-motion: reduce) { .xpagebar { transition: none; } }
/* the tool: set like FR/EN, mono and quiet, the chosen value in ink; the order is one toggle (the
   current order shows, a click flips it) */
.xtools { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px;
  font-family: var(--ui); font-size: var(--fs-tool); letter-spacing: .05em; }
body[data-view] .xsheet { padding-bottom: clamp(24px, 4vh, 48px); }
.xtools .xgrp { display: flex; gap: 6px; align-items: baseline; }
.xtools .sep { color: var(--rule); }
.xtools button { font: inherit; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--mut); white-space: nowrap; letter-spacing: .05em; }
.xtools button:hover { color: var(--ink); }
/* the chosen value in ink, never bold (the face has no bold: the browser faked one, Seba 04.10);
   Liste / Galerie underlined as well, as every Liste / Galerie switch */
.xtools button.is-on { color: var(--ink); }
.xtools button[data-view] { padding-bottom: 3px; border-bottom: 1px solid transparent; }
.xtools button[data-view].is-on { border-bottom-color: var(--ink); }
/* one toggle (expo-index.js flips it), as wide as its longer label whichever shows, so using the
   tool never changes the bar's layout; the label sits at its right end, so the tools end on the
   same right edge as FR/EN above them (Seba 04.10: "Chronologique ↑" stopped 40px short, the room
   of "Antichronologique ↓" after it) */
.xtools .xsort { display: grid; }
.xtools .xsort button { grid-area: 1 / 1; justify-self: end; }
.xtools .xsort button:not(.is-on) { visibility: hidden; }
.xtools .xsel-wrap { position: relative; display: flex; align-items: baseline; }
.xtools .xsel { color: var(--ink); }
.xtools .xsel-ar { margin-left: 6px; color: var(--mut); }
.xtools .xmenu { position: absolute; top: calc(100% + 16px); right: 0; z-index: 41;   /* drops from the page's bar */
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 13rem;
  padding: 12px 16px 14px; background: var(--bg); border: 1px solid var(--rule);
  box-shadow: 0 10px 30px rgba(26,26,26,.10); }
.xtools .xmenu[hidden] { display: none; }

/* ============================================================
   LISTE — archivio-uno mechanism, pure CSS
   ============================================================ */
.xlist { display: flex; flex-direction: column; }
.xitem { border-bottom: 1px solid var(--rule); }
.xitem:first-child { border-top: 1px solid var(--rule); }
.xitem.xhide { display: none; }

.xrow {
  display: grid;
  grid-template-columns: 4.4rem minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, .9fr) 10.5rem 1rem;
  column-gap: 20px; align-items: baseline;
  /* no horizontal inset: row text sits on the same 10px axis as the brand + section bars */
  padding: 7px 0; text-decoration: none; color: var(--ink);
  transition: background-color 160ms ease, opacity 160ms ease;
}
/* keyboard: the row the keyboard is on (:focus-visible), never one a mouse click left focused —
   :focus-within kept a clicked row lit and its preview open after the record closed (v110). Not
   the row a closing record hands the focus back to (.xquiet, tweaks-apply.js): closed with Esc,
   the browser counts that focus as keyboard focus and pinned its preview open over the list.
   Each :has() rule stands ALONE: in a list with :hover, a browser without :has() (Firefox ESR 115,
   Safari < 15.4) drops the whole rule, hover included (review 02.10). */
.xitem:hover > .xrow { background: var(--wash); opacity: .55; }
.xitem:not(.xquiet):has(> .xrow:focus-visible) > .xrow { background: var(--wash); opacity: .55; }
/* HOVER INTENT (see the .xrev note below) — the row state waits for the same rest delay,
   so a sweep across the list doesn't strobe a trail of highlights behind the pointer. */
.xitem:hover > .xrow { transition-delay: var(--xhover-intent, 160ms); }
/* an exhibition with no image, text or works: not clickable, no hover (client 3 Sept) */
.xitem.xstatic > .xrow { cursor: default; }
.xitem.xstatic:hover > .xrow { background: none; opacity: 1; }
.xitem:not(.xquiet):has(> .xrow:focus-visible) > .xrow { transition-delay: 0s; }
.xrow .xyr    { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); }
.xrow .xttl   { font-family: var(--body); font-size: var(--fs-body); }
.xrow .xlieu,
.xrow .xville { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xrow .xtick  { font-family: var(--ui); font-size: .6rem; color: var(--ph-ink); text-align: right; }

/* THE PREVIEW FLOATS OVER THE ROWS BELOW (meeting 1 Oct, v110). In the flow it pushed the next
   rows down, so the row you were heading for ran away under the pointer (Alexandra: "c'est pas
   possible de déplacer sa souris et que le truc il monte"). Now the list never moves: the preview
   lies over the rows below, on the right, where their year and title stay readable, and the
   pointer goes straight through it (pointer-events: none) to the next row, whose preview takes
   over. So nothing in it is a link: a click on the ROW opens the record. It opens below its row,
   or above it when the screen has no room below (.xup, measured on the preview's own height by
   tweaks-apply.js). Width per list: --xpeek-w (home.css sets Collections and Publications). */
.xitem { position: relative; }
/* THE MECHANISM: auto height animated as a grid track. The images inside load only once it
   opens, as they did when it was in the flow. The shadow is a filter, so a closed preview casts
   none; the frame is on the panel inside, so a closed preview shows no hairline. */
.xrev {   /* as wide as what it holds, up to --xpeek-w: works alone leave no empty band beside them */
  position: absolute; top: 100%; right: 0; z-index: 36; width: max-content; max-width: var(--xpeek-w, 56%);   /* above the page's bar (35) and the home's section bars (30), even one still mid-screen; under the site's bar (40) */
  display: grid; grid-template-rows: 0fr; pointer-events: none;
  filter: drop-shadow(0 10px 22px rgba(26,26,26,.12));
  transition: grid-template-rows 320ms cubic-bezier(.4, 0, .2, 1);
}
.xitem.xup > .xrev { top: auto; bottom: 100%; }
.xitem:hover > .xrev { grid-template-rows: 1fr; }
.xitem:not(.xquiet):has(> .xrow:focus-visible) > .xrev { grid-template-rows: 1fr; }
/* HOVER INTENT — it opens only once the pointer RESTS on a row, so a sweep across the list
   shows nothing. The delay sits on the :hover rule ONLY: closing never waits, and the keyboard
   opens it at once (rule below wins). The keyboard's preview paints over a hover preview that the
   parked pointer opens at the same time. */
.xitem:hover > .xrev { transition-delay: var(--xhover-intent, 160ms); }
.xitem:not(.xquiet):has(> .xrow:focus-visible) > .xrev { transition-delay: 0s; z-index: 37; }
.xrev > .xinner { overflow: hidden; }

/* the panel: the images (or works) on the left, the dates and the start of the text beside them —
   always side by side, so a preview stays one compact band (with the text under three works it
   reached 440px and covered ten rows). Same paper, hairline and shadow as the bar's type menu. */
.xpeek { display: flex; align-items: flex-start; gap: 24px;
  padding: 14px 16px 16px; background: var(--bg); border: 1px solid var(--rule); }
.xpeek-text { flex: 1 0 26ch; min-width: 0; }
.xpeek-text:not(:has(.xteaser)) { flex: 0 0 auto; }   /* dates alone take only their width */
.xpeek-meta { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; margin: 0 0 6px; }
/* the text is CUT, so the record is worth the click (meeting 1 Oct): ~220 characters in the
   engine (teaser()), at most 3 lines here */
.xdesc.xteaser { margin: 0; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }

/* The works (or the one image) at the shared --xthumb scale, each IDENTIFIED: title in italics,
   date (the Collections quick-look; moved here from home.css at v110 so every list has it).
   Works that need more than the panel's width shrink together, in proportion, instead of wrapping
   to a second row. Each figure carries its image's ratio (--r, set by the engines from the media's
   width/height): it is --xthumb high at full size, and the image fills its width at its own ratio,
   so a shrunk work is a smaller picture, never one in a grey box, and its place is held before it
   loads. All of them stand the same height, so they line up TOP and bottom whatever the length of
   their captions (aligned on the captions' foot, a four-line title pushed its picture 55px up). */
.xq-works { display: flex; gap: clamp(14px, 1.6vw, 26px); align-items: flex-start; flex: 0 1 auto; min-width: 0; }
/* a WIDTH, not a flex-basis: only a width counts in the row's own size, so the panel knows how
   much room the works want (with a basis, an image with no caption collapsed to nothing). Capped
   only for a panorama (ratio > 2): below that, every work keeps the common height. */
.xq-work { margin: 0; width: calc(var(--xthumb, 240px) * var(--r, .75)); max-width: calc(var(--xthumb, 240px) * 2); flex: 0 1 auto; min-width: 0; }
.xq-work img { display: block; width: 100%; height: auto; background: var(--ph); }
/* the box keeps the ratio the CMS states, loaded or not: the panel is measured (tweaks-apply.js)
   before its images load and never changes height after, and a media whose stated size is wrong
   (ASCRS427: 640×480 given, 480×640 real) is contained in its place instead of breaking the line */
.xq-work[style] img { aspect-ratio: var(--r); object-fit: contain; object-position: center bottom; }
/* a media without a known size (66): its own width at the fixed height, as before v110 (forced
   to the default ratio it sat in a grey band, review 02.10) */
/* (the same panorama cap as above; until it loads, a grey half-square holds its place) */
.xq-work:not([style]) { width: auto; min-width: calc(var(--xthumb, 240px) * .5); }
.xq-work img:not([height]) { width: auto; min-width: 100%; max-width: 100%; height: var(--xthumb, 240px); object-fit: contain; object-position: left bottom; }
.xq-work img.xbroken {
  background: repeating-linear-gradient(45deg, var(--ph), var(--ph) 5px, var(--ph-line) 5px, var(--ph-line) 6px); }
.xq-work figcaption { margin-top: 9px; display: flex; flex-direction: column; gap: 3px;
  font-family: var(--ui); font-size: .6rem; color: var(--mut);
  hyphens: auto; overflow-wrap: anywhere; }   /* a shrunk work is narrower than "pełnopostaciowy," */
.xq-artist {
  font-family: var(--ui); font-size: .6rem; letter-spacing: .02em; color: var(--ph-ink);
}
.xq-title { font-family: var(--body); font-size: var(--fs-meta); color: var(--ink); line-height: 1.45;
  /* 2 lines at most: the record has the whole title. A 101-character title in a narrow work ran
     to ten lines and lifted its preview under the bar (review 02.10). The date is its own line
     below, so the cut never takes it */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.xq-date { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; line-height: 1.45; }
.xq-title em { font-style: italic; }
.xq-more {
  flex: 0 0 auto; align-self: center; font-family: var(--ui); font-size: var(--fs-meta);
  letter-spacing: .04em; color: var(--mut); white-space: nowrap;
}

/* left column: the record's fields as a definition list */
.xfields { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut);
  display: grid; grid-template-columns: 7.2rem minmax(0, 1fr); gap: 2px 12px; margin: 0; }
.xfields dt { color: var(--ph-ink); letter-spacing: .02em; }
.xfields dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }   /* a long host in the website row ("museedartsdenantes.nantesmetropole.fr") breaks at 375px instead of pushing the sheet sideways */
.xfields dd a { color: var(--accent); }   /* the website row of an exhibition and of an actualité: no underline (Seba 12.10), as the Collections link below */

/* right column: the description, as the CMS wrote it (sanitised) */
.xdesc { font-family: var(--body); font-size: var(--fs-body); color: var(--ink);
  line-height: 1.55; max-width: 70ch; }
.xdesc p { margin: 0 0 .7em; }
.xdesc p:last-child { margin-bottom: 0; }
.xdesc a { color: var(--accent); }
/* a long URL in a description (ac-3's ticketing link) pushed the record 69px past a phone's edge */
.xdesc { overflow-wrap: anywhere; }
/* a title word wider than a phone's line ("GRUPPENAUSSTELLUNG", "elles@centrepompidou.") ran under the ✕
   and past the edge: broken where it must, hyphenated on phones — the design version's rule of 30.09 */
.xfiche-title { overflow-wrap: anywhere; }
@media (max-width: 900px) { .xfiche-title { hyphens: auto; } }

/* ============================================================
   GALERIE: since 04.10 the Galerie of Collections on every page (.xgalerie, below with the
   lists): the centrephotogeneve sticky stack and its 1/2/3/n columns are gone
   (Seba: "a bit of a mess"; one Liste / Galerie everywhere)
   ============================================================ */

/* ---- view switch ------------------------------------------- */
/* the PAGE's Liste and Galerie only (#xlist / #xgal): a record's own list ("Autres actualités",
   records.js) sits under the same body and was hidden with them in Galerie (review 04.10) */
body[data-view="galerie"] #xlist { display: none; }
body[data-view="list"]    #xgal  { display: none; }

.xwithheld { font-family: var(--ui); font-size: var(--fs-meta); color: var(--ph-ink);
  padding: 16px 4px; margin: 0; }

/* ============================================================
   FICHE — bespoke panel (ported from the reference), overlapping the index at 85%.
   NOT fiche.js: fiche.js stacks the image as a full-width hero on top, which is
   unreadable at this width (Seba's note on the screenshot). This lays the record
   out as a header (kicker · title · dates) over a two-column body (image | fields
   + description). Fixed overlay; the index underneath never moves, so the exposed
   left strip stays live (année + titre). Below 900px it goes near-full-width and
   the body stacks. On adoption this is what moves into the site (its own panel for
   the Expositions record. Since the 26 Aug API, an exhibition lists its works: the panel
   now also shows each work's record, with a back link — see "Œuvres présentées" below).
   ============================================================ */
.xfiche {
  position: fixed; top: 0; right: 0; z-index: 80;
  width: 85vw; height: 100vh; height: 100dvh;
  background: var(--bg); border-left: 1px solid var(--rule);
  box-shadow: -22px 0 70px rgba(26,26,26,0.20);
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain;                  /* its end never hands the scroll on to the page (07.10) */
  transform: translateX(100%);
  transition: transform .5s cubic-bezier(.77, 0, .175, 1);
}
body.xopen .xfiche:not(.xlayer), .xfiche.xlayer.xin { transform: none; }
/* THE PAGE HOLDS STILL UNDER A RECORD (Seba 07.10: scrolling on past a record's end scrolled the home, so
   closing every tab no longer brought the reader back where they had started; a short record, which
   cannot scroll itself, passed the wheel straight on): while a record is open the page cannot be
   scrolled and keeps its place; its scrollbar's room stays reserved, so nothing shifts sideways where
   scrollbars take room */
html:has(> body.xopen) { overflow: hidden; }
html { scrollbar-gutter: stable; }

/* CALQUES (engine: records.js, layout). A record opened from a record is a new sheet over the last;
   every sheet has one width for the window, and the sheets below slide left, each showing its left
   edge as a spine with its title (Alexandra: "l'indice de où on vient … comme des modèles de
   classeurs"). Seven at most, the first one kept; a full pile covers the screen (Seba 05.10). A
   covered sheet is unpainted and shadowless (only the top one casts the shadow); its spine is a
   separate fixed button that slides with it. Desktop only: phones keep the single panel. */
.xfiche.xcovered { box-shadow: none; transition: transform .5s cubic-bezier(.77, 0, .175, 1), box-shadow 0s linear .5s; }
/* unpainted once the incoming sheet has slid in (0.5s), not at the click: the page you came from no
   longer goes blank under a sheet that has barely started to move (review 03.10); uncovering is
   instant (no transition on the plain state) */
.xfiche.xcovered > .xfiche-inner { visibility: hidden; transition: visibility 0s linear .5s; }
.xtab { position: fixed; top: 0; bottom: 0; left: 0; width: var(--xtab, 40px); box-sizing: border-box; margin: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 18px 0;
  font: inherit; font-family: var(--ui); font-size: var(--fs-meta); letter-spacing: .04em; line-height: 1.2; color: var(--mut);
  background: var(--bg); border: 0; border-left: 1px solid var(--rule); cursor: pointer;
  /* placed by records.js (translateX), it slides with its sheet, on the sheets' own curve (05.10) */
  transition: transform .5s cubic-bezier(.77, 0, .175, 1), opacity .4s ease, background-color .16s ease, color .16s ease; }
@media (prefers-reduced-motion: reduce) { .xtab { transition: background-color .16s ease, color .16s ease; } }
/* the vertical text is on the span, not the <button>: older Safari forces form controls horizontal */
.xtab span { writing-mode: vertical-rl; transform: rotate(180deg);   /* a spine read from the bottom up */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-height: calc(100vh - 36px); }
.xtab:hover, .xtab:focus-visible { background: var(--wash); color: var(--ink); }
/* the foot of a record: a little air after its last line (Seba 04.10: "too much space empty at the
   bottom"; it was 20vh, 196px at 1512×982), counted inside its full height, and only on a record
   longer than its sheet (records.js fitFoot): one that fits (.xfit) does not scroll at all */
.xfiche-inner { padding: 14px clamp(16px,3vw,40px) clamp(32px, 5vh, 56px); min-height: 100%; box-sizing: border-box; }
.xfiche.xfit > .xfiche-inner { padding-bottom: 0; }

/* just a cross — no "Fermer" label, no box (Seba). Sized as a comfortable tap target;
   the accessible name lives on aria-label since the glyph alone carries no meaning. */
.xfiche-close {
  position: sticky; top: 0; float: right; z-index: 5;
  font: inherit; font-family: var(--ui); font-size: 1.6rem; line-height: 1;
  background: none; border: 0; padding: 4px 2px 8px 14px;
  cursor: pointer; color: var(--mut); transition: color .18s ease;
}
.xfiche-close:hover, .xfiche-close:focus-visible { color: var(--ink); }

.xfiche-title { font-family: var(--display); font-weight: 400; line-height: 1.03;
  font-size: clamp(2rem, 5vw, 4.6rem); margin: 0; max-width: 22ch; text-wrap: balance; }
.xfiche-dates { font-family: var(--display); font-weight: 400; line-height: 1.05;
  font-size: clamp(1.4rem, 3.2vw, 3rem); margin: 18px 0 0; color: var(--ink); }

.xfiche-body { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 40px; margin-top: 34px; align-items: start; }
.xfiche-fig { margin: 0; }
.xfiche-fig img { width: 100%; height: auto; display: block; background: var(--ph); }
.xfiche-fig figcaption { font-family: var(--ui); font-size: .62rem; color: var(--mut); margin-top: 6px; }
/* the image series (several images per record, client 3 Sept): one at a time, ‹ n/N ›,
   each with its own caption/credit */
.xseries .xs-stage[data-step] { cursor: e-resize; }
.xseries figcaption { display: flex; flex-direction: column; gap: 6px; }
.xs-nav { display: flex; align-items: baseline; gap: 10px; }
.xs-btn { font: inherit; font-size: .95rem; line-height: 1; background: none; border: 0; padding: 2px 4px;
  cursor: pointer; color: var(--mut); }
.xs-btn:hover, .xs-btn:focus-visible { color: var(--ink); }
.xs-count { color: var(--ink); }
.xs-cap { line-height: 1.55; }
.xs-cap p { margin: 0; }
/* no image: one text column, never an empty image slot (client 3 Sept) */
.xfiche-body.noimg { grid-template-columns: minmax(0, 1fr); }
.xfiche-side .xfields { grid-template-columns: 7.6rem minmax(0, 1fr); margin-bottom: 26px; }
.xfiche-side .xdesc { max-width: 62ch; }

/* ---- Œuvres présentées (under an exhibition) + the work record (client V2; API 26 Aug).
        Engine: expo-index.js worksBlock()/workHTML(). Same panel, same x* kit. ---- */
.xworks { margin-top: clamp(44px, 7vh, 80px); padding-top: 16px; border-top: 1px solid var(--rule); }
.xrel-h { font-family: var(--ui); font-size: var(--fs-meta); font-weight: 400; color: var(--mut); letter-spacing: .02em; margin: 0 0 16px; }
.xfiche-side .xrel-h { margin-top: 34px; }
.xworks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 30px 22px; align-items: start; }
/* a tile: the work stands on a common baseline in a square box (contain, never cropped) */
.xwork { font: inherit; display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 0; cursor: pointer; color: var(--ink); }
.xw-img { display: block; aspect-ratio: 1 / 1; }
.xw-img:empty { background: var(--ph); }          /* a work without an image keeps the grid's rhythm */
.xw-img img { width: 100%; height: 100%; object-fit: contain; object-position: center bottom;
  transition: opacity .18s ease; }
.xwork:hover .xw-img img, .xwork:focus-visible .xw-img img { opacity: .72; }
.xw-ttl { display: block; font-family: var(--body); font-style: italic; font-size: .92rem;
  line-height: 1.3; margin-top: 9px; }
.xw-date { display: block; font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); margin-top: 3px; }

.xfiche-link { margin: 22px 0 0; font-family: var(--ui); font-size: var(--fs-meta); }
/* a link that opens a record on this page is a button styled as the link (records.js) */
.xfiche-link button { font: inherit; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent); border-bottom: 1px solid var(--rule); }

/* ---- the sheet's tools: ✕, and "Tout fermer" once two sheets or more are stacked (Seba 03.10:
        "otherwise user needs to close one by one"). Sticky at the top right, as the ✕ was. ---- */
.xsheet-tools { position: sticky; top: 0; float: right; z-index: 5; display: flex; align-items: baseline; gap: 14px;
  background: linear-gradient(var(--bg) 70%, transparent); padding-left: 14px; }
.xsheet-tools .xfiche-close { position: static; float: none; }
.xclose-all { font: inherit; font-family: var(--ui); font-size: var(--fs-meta); letter-spacing: .02em; color: var(--mut);
  background: none; border: 0; padding: 4px 0; cursor: pointer; white-space: nowrap; }
.xclose-all:hover, .xclose-all:focus-visible { color: var(--ink); }
body:not(.xpile) .xclose-all { display: none; }
/* a relation whose data is still on its way (records.js): the click was heard */
.xwait { cursor: progress; opacity: .55; }

/* ---- a public collection's record (records.js; was home.css until v114: a collection now opens from
        a work on any page) ---- */
.xfiche-place { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; margin: 14px 0 0; }
.xcoll-sub { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; margin: 20px 0 0; }
.xcoll-ext { margin: 14px 0 0; font-family: var(--ui); font-size: var(--fs-meta); }
.xcoll-ext a { color: var(--accent); }   /* no underline on a website link (Seba 12.10) */
.xcoll-works { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 30px 26px; margin-top: 30px; align-items: start; }
.xcoll-work { margin: 0; }
.xcoll-work img { width: 100%; height: auto; display: block; background: var(--ph); }
/* the IMAGE opens the work's record as a new sheet; the caption stays selectable text */
.xcoll-wlink { display: block; width: 100%; padding: 0; margin: 0; border: 0; background: none; cursor: pointer; }
.xcoll-wlink img { transition: opacity .18s ease; }
.xcoll-wlink:hover img, .xcoll-wlink:focus-visible img { opacity: .72; }
.xcoll-work figcaption { font-family: var(--ui); font-size: .62rem; color: var(--mut); line-height: 1.55; margin-top: 8px; }
.xcoll-work figcaption em { font-style: italic; }
/* ‹ n/N › through the list a record was opened from (every list of the site since 06.10: the home's
   and the four list pages'); the record slides in from the side you go to */
.xseq { display: flex; align-items: baseline; gap: 10px; margin: 0 0 12px; font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); }
.x-from-r { animation: xFromR .32s cubic-bezier(.22,.61,.36,1); }
.x-from-l { animation: xFromL .32s cubic-bezier(.22,.61,.36,1); }
@keyframes xFromR { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
@keyframes xFromL { from { opacity: 0; transform: translateX(-28px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .x-from-r, .x-from-l { animation: none; } }
.xback { font: inherit; font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; background: none; border: 0; padding: 6px 0;
  margin: 0 0 18px; cursor: pointer; text-align: left; max-width: calc(100% - 3rem); display: block; }
.xback:hover, .xback:focus-visible { color: var(--ink); }
.xwk-title { font-style: italic; }
.xwk-cap { font-family: var(--ui); font-size: .72rem; line-height: 1.6; color: var(--mut); }
.xwk-cap em { color: var(--ink); }
.xrel { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); max-width: 62ch; }
.xrel li { border-bottom: 1px solid var(--rule); }
.xrel button,
.xrel a { font: inherit; display: grid; grid-template-columns: 3.4rem minmax(0, 1fr);
  column-gap: 12px; align-items: baseline; width: 100%; text-align: left; background: none; border: 0;
  padding: 7px 0; color: var(--ink); font-family: var(--body); font-size: .92rem; line-height: 1.35; }
.xrel button, .xrel a { cursor: pointer; transition: background-color .16s ease; }
.xrel button:hover, .xrel button:focus-visible, .xrel a:hover, .xrel a:focus-visible { background: var(--wash); }
.xrel .xyr { font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); }

@media (max-width: 900px) {
  .xfiche { width: 94vw; }                 /* near-full-screen; a sliver keeps the close affordance */
  .xfiche-body { grid-template-columns: 1fr; gap: 24px; }
  .xfiche-title { font-size: clamp(1.7rem, 8vw, 2.6rem); }
  .xfiche-dates { font-size: clamp(1.2rem, 5vw, 1.8rem); }
  .xworks-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px 14px; }
  /* Phone: year + TITLE ONLY. The venue column used to take half the width, squeezing
     "Broken: The Power of the Fragment in Sculpture" into four wrapped lines and truncating
     the venue anyway ("NATIONAL GALL…"). Everything else is one tap away in the fiche. */
  .xrow { grid-template-columns: 3.6rem minmax(0, 1fr); }
  .xrow .xlieu,
.xrow .xville,
.xrow .xtick { display: none; }
  .xrev { display: none; }              /* no hover on touch: tap opens the fiche */
}
/* a screen nothing can hover (a touch tablet): a tap opens the record, and a hover the tap leaves
   behind would keep a preview floating over the list */
@media (any-hover: none) { .xrev { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .xrev { transition-duration: 1ms; }
}

/* ============================================================
   COLLECTIONS PUBLIQUES + PUBLICATIONS — the two lists of the home, collections.html and
   publications.html (moved here from home.css at v119, Seba 04.10: each list got its own page).
   Reuses the kit above (.xlist/.xrow/.xitem/.xrev/.xfiche). Collections: the institution rows,
   their hover quick-look (a strip of work thumbnails) and the fiche body (the
   institution's works as a grid). Engine: wireframe.js. Data: window.AS_COLL.
   ============================================================ */
.xlist.coll .xttl { font-family: var(--body); font-size: var(--fs-body); }

/* Hover quick-look — up to 3 IDENTIFIED works at the shared --xthumb scale. Artist is
   deliberately subordinate: it is "Alina Szapocznikow" on all 110 works, so the varying
   information — title, date — carries the line. The panel and the .xq-* works moved to
   expo-index.css at v110 (every list floats its preview now). Here only its width: up to 66%, so
   the three works keep (nearly) their full 240px, but never closer to the row's start than the
   longest institution name (24.5 title-ems, "Musée national germanique, Nuremberg, Allemagne"),
   whose share of the row grows as the window narrows (at 66% it was covered below ~1250px,
   review 02.10). The % and the type size both resolve on the preview: the row's width, the
   title's size. */
.xlist.coll { --xpeek-w: min(66%, calc(100% - 26 * var(--fs-body))); }

/* the collection's record (place, works grid…) is drawn by records.js, styled in expo-index.css (v114) */

/* ---- Publications list (same kit; fiche reuses .xfiche-body) ---- */
.xlist.pub { --xpeek-w: 40%; }   /* the floating cover (expo-index.css) clears the titles of the rows below */
.xlist.pub .xttl { font-family: var(--body); font-size: var(--fs-body); }

/* ---- ONE ROW FOR EVERY LIST (Seba 04.10): image · title, with its date at the FOOT of the row ·
        where · city, country · ▸, in the same columns on the home and on every page (Actualités,
        Expositions, Collections publiques, Publications), so they line up from one section to the
        next and read the same. Where = the venue, the publisher, or nothing for an institution (its
        name is the title). City, country = the country where the CMS has one (exhibitions and
        publications have none yet: asked of Christophe). The type left the rows: it is in the record,
        and in the pages' filters. The date: the year, the full dates for the actualités (an agenda:
        the day matters); an institution has none. It sat in its own column on the left until it went
        under the title, at the bottom of the row (Seba 04.10, for Alexandra to see: the client asked
        for the year on the left, 5 Sept p.14). The image is whole, centred in a 4:3 frame in the
        middle of the row's height, and the row is as tall as the image unless a long title needs more.
        Two grid rows: the title, the venue and the place on the first (their baselines aligned), the
        date alone on the second, which takes the rest of the image's height. Rows: wireframe.js,
        expo-index.js, actu-index.js, records.js acRow. ---- */
.xlist.xstd { --xth-w: clamp(110px, 10vw, 150px); }
.xlist.xstd .xrow { grid-template-columns: var(--xth-w) minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1.1fr) 1rem;
  grid-template-rows: auto 1fr; row-gap: 6px; padding: 10px 0; }
.xlist.xstd .xrow > .xthumb { grid-column: 1; grid-row: 1 / span 2; }
.xlist.xstd .xrow > .xttl   { grid-column: 2; grid-row: 1; text-wrap: pretty; }
/* the title keeps clear of the venue (Seba 04.10: a long title ran up against it): its column holds
   room on the right, so it breaks onto a second line sooner. The columns stay where they are, so
   the lists still line up with each other */
@media (min-width: 901px) { .xlist.xstd .xrow > .xttl { padding-right: clamp(28px, 4.5vw, 88px); } }
.xlist.xstd .xrow > .xyr    { grid-column: 2; grid-row: 2; align-self: end; line-height: 1.5; }
.xlist.xstd .xrow > .xlieu  { grid-column: 3; grid-row: 1; }
.xlist.xstd .xrow > .xville { grid-column: 4; grid-row: 1; }
.xlist.xstd .xrow > .xtick  { grid-column: 5; grid-row: 1; }
/* the row is as tall as its image: the venue and the place wrap instead of being cut */
.xlist.xstd .xrow .xlieu, .xlist.xstd .xrow .xville { white-space: normal; overflow: visible; line-height: 1.5; }
/* a row that is a button (an actualité: it opens in place, on the home and in a record) looks like the links */
.xlist button.xrow { font: inherit; letter-spacing: inherit; width: 100%; margin: 0; border: 0; background: none;
  text-align: left; cursor: pointer; -webkit-appearance: none; appearance: none; }
.xthumb { align-self: center; display: block; aspect-ratio: 4 / 3; }   /* out of the row's baseline alignment */
.xthumb img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: center; }
/* no image, nor any work's: a white frame keeps the column (Seba 04.10: white, not grey) and prints
   the title in it, in the face and colour of the Galerie's (.xg-t), so the row is not empty (Seba
   04.10). As many lines as the frame holds, the rest cut. */
.xthumb-none { display: flex; align-items: center; justify-content: center; text-align: center;   /* centred, as in the Galerie */
  background: #fff; padding: 8px 9px; box-sizing: border-box; overflow: hidden; }
.xthumb-t { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; line-clamp: 5; overflow: hidden;
  font-family: var(--display); font-size: .74rem; line-height: 1.2; color: var(--mut); text-wrap: balance; overflow-wrap: anywhere; }
@media (max-width: 900px) { .xthumb-none { padding: 5px 6px; } .xthumb-t { font-size: .6rem; -webkit-line-clamp: 4; line-clamp: 4; } }
@media (max-width: 900px) {
  .xlist.xstd { --xth-w: 88px; }
  .xlist.xstd .xrow { grid-template-columns: var(--xth-w) minmax(0, 1fr); column-gap: 14px; row-gap: 4px; }
}
/* inside a record (the "Autres actualités"), a sheet narrower than a page: image · title and date */
.xac-rel { container: xrel / inline-size; }
@container xrel (max-width: 820px) {
  .xlist.xstd .xrow { grid-template-columns: var(--xth-w) minmax(0, 1fr); }
  .xlist.xstd .xrow .xlieu, .xlist.xstd .xrow .xville, .xlist.xstd .xrow .xtick { display: none; }
}

/* the Liste / Galerie switch (client 5 Sept p.15; every list since 04.10) */
.pubview { display: flex; gap: 16px; justify-content: flex-end; margin: 0 0 14px;
  font-family: var(--ui); font-size: var(--fs-tool); letter-spacing: .05em; }
.pubview button { font: inherit; background: none; border: 0; border-bottom: 1px solid transparent;
  padding: 0 0 3px; cursor: pointer; color: var(--mut); }
.pubview button:hover { color: var(--ink); }
.pubview button.is-on { color: var(--ink); border-bottom-color: var(--ink); }   /* in ink and underlined, never bold (a faked bold, Seba 04.10) */
/* EN COURS / À VENIR (Seba 04.10, as the Actualités button's list): the agenda's two groups, each
   under its heading, on the home and on the Actualités page, in the Liste and the Galerie
   (home.js, actu-index.js) */
.xgroup { display: block; margin: 0; padding: 30px 0 10px; font-family: var(--ui); font-size: var(--fs-meta);
  color: var(--mut); letter-spacing: .02em; }
.xgroup:first-child { padding-top: 4px; }
.xgroup[hidden] { display: none; }
.xgroup + .xitem { border-top: 1px solid var(--rule); }   /* the first row under a heading keeps its top rule */
.xgalerie > .xgroup { grid-column: 1 / -1; padding: 0; }
.xgalerie > .xgroup ~ .xgroup { padding-top: 14px; }
/* THE GALERIE (one name for it everywhere, Seba 04.10): every image whole (contain), centred on
   white (v111); an item without an image keeps its place as a typographic tile */
.xgalerie { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 34px 22px; align-items: start; }   /* 5 across (Seba 04.10; it filled up to 7) */
.xgalerie > .xhide { display: none; }   /* the pages' filters (Expositions, Actualités) */
.xgalerie[hidden], .xlist[hidden] { display: none; }   /* .xlist's display:flex would beat [hidden] */
.xg-item { font: inherit; display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 0; cursor: pointer; color: var(--ink); text-decoration: none; }   /* a link on Expositions and Actualités, a button elsewhere */
.xg-item.xstatic { cursor: default; }   /* an exhibition with nothing beyond its Galerie item: opens nothing, as its row */
/* each image (a cover, a collection's first work) WHOLE, centred on white (meeting 1 Oct) */
.xg-img { display: flex; align-items: center; justify-content: center; aspect-ratio: 3 / 4;
  background: #fff; padding: 10px; box-sizing: border-box; }
.xg-img img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain;
  box-shadow: 0 1px 6px rgba(26,26,26,.12); transition: transform .3s ease; }
.xg-item:hover .xg-img img, .xg-item:focus-visible .xg-img img { transform: translateY(-3px); }
/* the institution open behind its record, marked in the Galerie as its row is in the Liste (markColl,
   wireframe.js; it had the class and no style: review 04.10) */
.xgalerie .xg-item.is-current .xg-img { background: var(--wash); box-shadow: inset 3px 0 0 var(--ink); }
.xg-none { background: #fff; padding: 14px; text-align: center; }   /* no image: its title on white (white, not grey), centred in the frame (Seba 04.10; it sat at the top left) */
.xg-t { font-family: var(--display); font-size: 1rem; line-height: 1.2; color: var(--mut); text-wrap: balance; }
.xg-yr { display: block; font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); margin-top: 10px; }
.xg-ttl { display: block; font-family: var(--body); font-size: .92rem; line-height: 1.3; margin-top: 2px; }
.xg-img + .xg-ttl { margin-top: 10px; }   /* no date (an institution): the title takes the date's place */
/* every Galerie item as its row (Seba 04.10): the date, the title, then where and the place */
.xg-pl { display: block; font-family: var(--ui); font-size: var(--fs-meta); color: var(--mut); letter-spacing: .02em; line-height: 1.5; margin-top: 4px; }
@media (max-width: 900px) { .xgalerie { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 14px; } }

/* the current institution marked in the list behind its record (client 5 Sept
   p.13); its ‹ n/17 › and slide-in live in expo-index.css with the records (v114) */
/* body: one notch above the keyboard rule of expo-index.css (0,5,0, earlier in this file), which since
   v110 tied it and faded the marked row to .55 under keyboard focus (review 02.10) */
/* the same mark for the actualité and the exhibition open on the home (wireframe.js markIn) */
body .xlist.xstd .xitem.is-current > .xrow { background: var(--wash); box-shadow: inset 3px 0 0 var(--ink); opacity: 1; }

/* Every list's preview in the MIDDLE of the screen, under the bar, wherever the row is (Seba 04.10:
   under its row, opening below or above it, it "appears in a random position every time"; first
   Collections and Publications, then "applied everywhere": Expositions on the home and its page,
   the Actualités page). Still pointer-transparent, so the pointer moves on to the next row;
   tweaks-apply.js measures it against the whole screen and never flips it (.xup). Every list with
   a preview is an .xstd list. Phones and touch screens have no preview (above). */
body .xlist.xstd .xitem > .xrev {
  position: fixed; top: calc(50% + (var(--bar-under, 53px) + var(--xbar2, 0px)) / 2); bottom: auto; left: 50%; right: auto;   /* under the site's bar (--bar-under) and the page's or section's bar (--xbar2) */
  transform: translate(-50%, -50%); max-width: min(860px, calc(100vw - 40px)); }

/* its row scrolled off the screen (a preview held open by the keyboard): it closes (tweaks-apply.js) */
body .xlist.xstd .xitem.xoff > .xrev { grid-template-rows: 0fr; }   /* (0,5,1): above the keyboard rule that opens it */
/* a book's preview: its cover, its year and its title, as in the Galerie
   (.xg-yr / .xg-ttl, Seba 04.10); a long title runs to four lines, the record has it whole */
.xq-work.xq-pub figcaption { gap: 2px; hyphens: manual; overflow-wrap: normal; }   /* a book's title is never cut mid-word ("Ali-na") */
.xq-work.xq-pub .xq-title { font-size: .92rem; line-height: 1.3; -webkit-line-clamp: 4; line-clamp: 4; }
