/* Paintings (vision §E2): head, sticky toolbar (search, facet popovers, sort, view, Wall; a sheet
   below 600px), the justified grid, the list, the empty state, the closing strip, and the Wall room
   (vision §F2's DOM twin inside [data-gl-host="wall"]).
   Markup: gallery.html + js/v3/pages/gallery.js + js/v3/features/{filters,justified,listview}.js. */
@layer pages {
  /* A legacy /gallery#P0162 link leaves for the painting before anything shows (inline head script). */
  :root[data-legacy-art] main { visibility: hidden; }

  /* Draft facets (motif, medium) show where drafts show; production reveals them once approved. */
  :root:not([data-drafts]) .facet-trigger[data-draft-only]:not([data-available]) { display: none; }
  .facet-trigger[data-unavailable] { display: none; }

  .gallery { display: block; }

  /* ------------------------------------------------------------------------------- head */
  .gallery-head {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: var(--gutter);
    row-gap: var(--space-4);
    padding-block: clamp(var(--space-5), 4vw, var(--space-7)) clamp(var(--space-5), 3vw, var(--space-6));
  }
  .gallery-head > * { grid-column: 1 / -1; margin: 0; }
  @media (min-width: 1024px) {
    .gallery-head > * { grid-column: 1 / span 8; }
  }
  .gallery-head__title {
    display: flex;
    align-items: flex-start;
    gap: 0.22em;
    font-size: var(--step-5);
    font-weight: 360;
    line-height: 0.98;
    letter-spacing: -0.015em;
  }
  /* The count, set like a catalogue number against the cap height. */
  .gallery-head__count {
    margin-block-start: 0.34em;
    font: 450 var(--step--1)/1 var(--font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.08em;
    color: var(--ink-2);
  }
  .gallery-head__lead { max-inline-size: 52ch; color: var(--ink-2); }
  .gallery-head__lead a { color: var(--ink); }
  /* Phones: the fallback face wraps the lead to 4 lines, Instrument Sans to 3; keep the 4th line's
     room so the toolbar and grid don't jump up when the font arrives (Phase 4 perf, gallery CLS). */
  @media (max-width: 599.98px) { .gallery-head__lead { min-block-size: 4lh; } }
  .gallery-head__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-block-start: var(--space-1);
  }
  .gallery-head__actions > .button { white-space: nowrap; }
  /* The Look slowly button may join after the first paint: on narrow phones both buttons are made
     to share one row, so its arrival never moves the toolbar or the paintings below. */
  @media (max-width: 419.98px) {
    .gallery-head__actions { flex-wrap: nowrap; gap: var(--space-2); }
    .gallery-head__actions > .button { flex: none; padding-inline: 11px; font-size: 0.875rem; letter-spacing: 0; }
  }
  /* Below the 360px design minimum (WCAG reflow at 320px): a little smaller still. */
  @media (max-width: 359.98px) {
    .gallery-head__actions { gap: 6px; }
    .gallery-head__actions > .button { padding-inline: 7px; font-size: 0.78125rem; }
  }

  /* ------------------------------------------------------------------------------- toolbar (e1) */
  /* The toolbar's containing block: it sticks while the results are on screen and lets go before
     the closing strip. */
  .gallery-browse { position: relative; }
  .gallery-bar {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    background: var(--raised);
    box-shadow: var(--e1), 0 1px 0 var(--rule);
  }
  /* Row 1 narrows the set (search, facets); row 2 says what is shown (count, active filters) and how
     (sort, view, Wall). */
  .gallery-bar__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    padding-block: 10px 6px;
  }
  .gallery-bar__status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    min-block-size: 44px;
    padding-block: 2px 10px;
  }

  /* Search: the label is visually hidden (the placeholder never stands in for it) and a lens says
     what the field is for. */
  .gallery-search {
    position: relative;
    flex: 1 1 15rem;
    min-inline-size: 11rem;
    max-inline-size: 24rem;
  }
  .gallery-search::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: 13px;
    z-index: 1;
    inline-size: 18px;
    block-size: 18px;
    margin-block: auto;
    background: var(--ink-2);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.25 15.25L20 20'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.25 15.25L20 20'/%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
  }
  .gallery-search__input {
    min-block-size: 44px;
    padding-block: 9px;
    padding-inline: 40px 12px;
    font-size: var(--step-0);
  }
  .gallery-search__input::-webkit-search-cancel-button { cursor: pointer; }

  .gallery-facets { display: flex; flex-wrap: wrap; gap: 6px; }
  .facet-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
    min-block-size: 44px;
    padding: 0 12px 0 14px;
    border: 1px solid var(--edge);
    border-radius: var(--radius-1);
    background: transparent;
    color: var(--ink);
    font: 500 var(--step--1)/1 var(--font-ui);
    letter-spacing: 0.01em;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color var(--dur-quick) var(--ease-set), background-color var(--dur-quick) var(--ease-set);
  }
  .facet-trigger::after {
    content: "";
    inline-size: 12px;
    block-size: 12px;
    background: currentColor;
    opacity: 0.7;
    -webkit-mask: var(--icon-chevron) center / contain no-repeat;
    mask: var(--icon-chevron) center / contain no-repeat;
    rotate: 90deg;
    transition: rotate var(--dur-quick) var(--ease-set);
  }
  .facet-trigger:hover { border-color: var(--ink-2); }
  .facet-trigger[data-active],
  .facet-trigger:has(+ :popover-open) { border-color: var(--ink); }
  .facet-trigger:has(+ :popover-open) { background: color-mix(in oklab, var(--ink) 6%, transparent); }
  .facet-trigger:has(+ :popover-open)::after { rotate: -90deg; }
  .facet-trigger__n:empty { display: none; }
  .facet-trigger__n {
    min-inline-size: 1.5em;
    padding: 3px 4px 2px;
    border-radius: var(--radius-1);
    background: var(--ink);
    color: var(--ground);
    font: 500 11px/1 var(--font-mono);
    text-align: center;
    font-variant-numeric: tabular-nums;
  }

  .gallery-filter-open { display: none; }
  .gallery-filter-open__n:empty { display: none; }

  .gallery-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-inline-start: auto;
  }
  .gallery-sort { display: flex; align-items: center; gap: var(--space-2); }
  .gallery-sort__label {
    font: 600 var(--step--2)/1 var(--font-ui);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-2);
  }
  .gallery-sort__select {
    inline-size: auto;
    min-block-size: 44px;
    padding-block: 9px;
    font-size: var(--step--1);
    background-color: transparent;
  }
  .gallery-view > label { min-block-size: 38px; }
  .gallery-wall-open { min-block-size: 44px; padding-inline: 14px 16px; font-size: var(--step--1); font-weight: 500; }
  /* A tiny salon hang: frames of different shapes. */
  .gallery-wall-open__glyph {
    inline-size: 18px;
    block-size: 14px;
    background:
      linear-gradient(currentColor, currentColor) 0 0 / 7px 8px no-repeat,
      linear-gradient(currentColor, currentColor) 9px 0 / 9px 5px no-repeat,
      linear-gradient(currentColor, currentColor) 9px 7px / 4px 7px no-repeat,
      linear-gradient(currentColor, currentColor) 0 10px / 7px 4px no-repeat,
      linear-gradient(currentColor, currentColor) 15px 7px / 3px 7px no-repeat;
    opacity: 0.8;
  }

  /* The stamped count shows only once it describes the results (a link may carry filters). */
  :root:not([data-gallery]) .gallery-status { visibility: hidden; }
  .gallery-status {
    flex: none;
    margin: 0;
    font: 500 var(--step--1)/1.3 var(--font-ui);
    color: var(--ink-2);
    white-space: nowrap;
  }
  .gallery-status__n { font: 500 var(--step--1)/1 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
  .gallery-chips {
    flex: 1 1 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-inline-size: 0;
  }
  .gallery-chips[hidden] { display: none; }
  .gallery-chips .chip { min-block-size: 32px; }
  .gallery-clear { min-block-size: 32px; padding-block: 4px; font-size: var(--step--1); }

  /* Tablets: the same controls, a little tighter; active filters get a line of their own under the
     count and the tools, so the tools never move when a filter is added. */
  @media (min-width: 600px) and (max-width: 1023.98px) {
    /* Wide enough for its placeholder; alone on its line (when the facets wrap) it takes the line. */
    .gallery-search { flex: 1 1 14.25rem; min-inline-size: 14.25rem; max-inline-size: none; }
    .gallery-facets { gap: 4px; }
    .facet-trigger { padding-inline: 11px 10px; }
    .gallery-chips { order: 3; flex: 1 1 100%; }
    .gallery-chips:not([hidden]) { padding-block-end: 2px; }
  }
  /* Phones: search, [Filter (n)] and the count; facets, sort, view and the Wall live in the sheet. */
  @media (max-width: 599.98px) {
    .gallery-bar__row { flex-wrap: nowrap; padding-block-start: 8px; }
    .gallery-bar__row > .gallery-facets,
    .gallery-bar__status > .gallery-tools { display: none; }
    .gallery-search { flex: 1 1 0; min-inline-size: 0; max-inline-size: none; }
    .gallery-filter-open { display: inline-flex; flex: none; min-block-size: 44px; padding-inline: 16px; }
    .gallery-bar__status { min-block-size: 40px; gap: var(--space-3); flex-wrap: nowrap; padding-block-end: 8px; }
    /* One line of chips that scrolls sideways, so the bar stays short. */
    .gallery-chips {
      flex-wrap: nowrap;
      overflow-x: auto;
      overscroll-behavior-x: contain;
      scrollbar-width: none;
      padding-block: 2px;
      margin-inline-end: calc(-1 * var(--margin));
      padding-inline-end: var(--margin);
    }
    .gallery-chips::-webkit-scrollbar { display: none; }
    .gallery-chips > * { flex: none; }
  }

  /* ------------------------------------------------------------------------------- facets */
  .facet-pop {
    inline-size: min(27rem, 100vw - 2 * var(--margin));
    max-inline-size: none;
    padding: var(--space-4) var(--space-4) var(--space-5);
  }
  .facet { display: grid; gap: var(--space-2); }
  .facet__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
  .facet__title {
    margin: 0;
    font: 600 var(--step--2)/1.3 var(--font-ui);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink);
  }
  .facet__hint { margin: 0 0 var(--space-2); font-size: var(--step--1); line-height: 1.4; color: var(--ink-2); }
  .facet__chips { display: flex; flex-wrap: wrap; gap: 6px; }

  /* ------------------------------------------------------------------------------- sheet */
  .gallery-sheet .dialog__body { display: grid; gap: var(--space-6); padding-block-end: var(--space-6); }
  .gallery-sheet__facets { display: grid; gap: var(--space-5); }
  .gallery-sheet__facets > .facet + .facet { padding-block-start: var(--space-5); border-block-start: 1px solid var(--rule); }
  .gallery-sheet__group { display: grid; gap: var(--space-3); padding-block-start: var(--space-5); border-block-start: 1px solid var(--rule); }
  .gallery-sheet .gallery-tools { margin: 0; justify-content: flex-start; gap: var(--space-4); }
  .gallery-sheet .gallery-sort { flex: 1 1 100%; }
  .gallery-sheet .gallery-sort__select { flex: 1; }
  .gallery-sheet .dialog__foot { justify-content: space-between; }
  .gallery-sheet .dialog__foot .button--slab { flex: 1 1 auto; max-inline-size: 22rem; }

  /* ------------------------------------------------------------------------------- results */
  .gallery-results { padding-block: var(--space-6) var(--space-9); }
  .gallery-drafts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin: 0 0 var(--space-5);
    font-size: var(--step--1);
    color: var(--ink-2);
  }
  .gallery-drafts[hidden] { display: none; }

  /* The justified grid. Rows are flex lines: every tile's basis is its aspect ratio × the row height
     and it grows by its aspect ratio, so a full row fills the width with every image at one height;
     the last row's spacer (flex-grow 999) keeps it at the target height. */
  .pgrid {
    --row-h: 300px;
    --gap: 16px;
    --row-gap: 44px;
    --chunk-pad: 104px;
    display: flex;
    flex-direction: column;
    gap: var(--row-gap);
    isolation: isolate; /* the chunks' z-index stays below the sticky toolbar */
  }
  :root.js .pgrid[data-state="loading"] { min-block-size: 140svh; }
  @media (max-width: 1023.98px) {
    .pgrid { --row-h: 220px; --row-gap: 36px; --chunk-pad: 80px; }
  }
  @media (max-width: 599.98px) {
    .pgrid { --row-h: 160px; --gap: 12px; --row-gap: 28px; --chunk-pad: 56px; }
  }
  /* Chunks of rows skip rendering while far off screen. content-visibility clips painting to the
     chunk's box, so the box reaches past the tiles far enough for their lamp pools; it does not take
     pointer events (chunks overlap a little), the tiles do. */
  .pgrid__chunk {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--row-gap);
    margin: calc(-1 * var(--chunk-pad)) calc(-1 * var(--margin));
    padding: var(--chunk-pad) var(--margin);
    content-visibility: auto;
    contain-intrinsic-size: auto 1800px;
    pointer-events: none;
  }
  .pgrid__row { display: flex; align-items: flex-start; gap: var(--gap); }
  .pgrid__row--last::after { content: ""; flex: 999 1 0; }
  /* The stamped newest paintings (gallery.html) before the page's inline script rows them, or
     without JavaScript: the same tiles, wrapped by the browser. A link with filters hides them
     until the module draws its own results. */
  .pgrid__row--wrap { flex-wrap: wrap; row-gap: var(--row-gap); }
  .pgrid__row--wrap::after { content: ""; flex: 999 1 0; }
  .pgrid[data-stamp="off"] > [data-stamp] { visibility: hidden; }
  .ptile {
    flex: var(--ar) 1 calc(var(--ar) * var(--row-h));
    min-inline-size: 0;
    pointer-events: auto;
  }
  .ptile > .tile__img { grid-area: 1 / 1; }
  /* Arriving images: the painting's dominant colour at its true shape, then the pixels fade in
     (180 ms; instant in Calm). Images on screen at load are never faded (they hold the LCP). */
  .ptile::after {
    content: "";
    grid-area: 1 / 1;
    background: var(--dom, var(--sunken));
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-quick) var(--ease-set);
  }
  .ptile[data-loading]::after { opacity: 1; transition: none; }
  .ptile .label { --label-size: var(--step-0); padding-inline-end: 4px; }
  .ptile .label__title { overflow-wrap: anywhere; }
  @media (max-width: 599.98px) {
    .ptile { gap: var(--space-2); }
    .ptile .label { --label-size: var(--step--1); }
  }

  /* ------------------------------------------------------------------------------- list */
  .plist-wrap[hidden] { display: none; }
  .plist__table tbody th { font-weight: 400; }
  .plist__table td, .plist__table th { padding-block: var(--space-2); }
  .plist__thumb-col { inline-size: 1%; }
  .plist__thumb a { display: block; inline-size: max-content; }
  .plist__thumb .table__thumb { block-size: 56px; inline-size: auto; max-inline-size: 128px; object-fit: contain; }
  .plist__title { font-size: var(--step-0); text-decoration-color: transparent; }
  .plist__title:is(:hover, :focus-visible) { text-decoration-color: var(--accent); }
  .plist__mood { color: var(--ink-2); }
  @media (min-width: 1024px) {
    .plist__medium { white-space: nowrap; }
  }
  @media (max-width: 599.98px) {
    .plist__table { min-inline-size: 44rem; }
    .plist__thumb .table__thumb { block-size: 48px; }
  }

  /* ------------------------------------------------------------------------------- empty state */
  .gallery-empty { display: grid; justify-items: start; gap: var(--space-5); padding-block: var(--space-7) var(--space-8); }
  .gallery-empty[hidden] { display: none; }
  .gallery-empty__title {
    margin: 0;
    max-inline-size: 24ch;
    font: 400 var(--step-3)/1.12 var(--font-display);
    letter-spacing: -0.005em;
    text-wrap: balance;
  }
  .gallery-empty__text { margin: 0; max-inline-size: var(--measure); color: var(--ink-2); }
  .gallery-empty__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .gallery-empty__chip .chip__count { color: var(--ink-2); }

  .gallery-noscript { padding-block: var(--space-6); max-inline-size: var(--measure); color: var(--ink-2); }

  /* ------------------------------------------------------------------------------- closing strip */
  /* The question, then the way to ask it: one reading line, left on the wall like a wall text. */
  .gallery-closing {
    display: grid;
    justify-items: start;
    gap: var(--space-4);
    padding-block: var(--space-8) var(--section);
    border-block-start: 1px solid var(--rule);
  }
  .gallery-closing > p { margin: 0; }
  .gallery-closing__line {
    font: 400 var(--step-3)/1.12 var(--font-display);
    letter-spacing: -0.005em;
    text-wrap: balance;
    max-inline-size: 26ch;
  }
  .gallery-closing__link { font-size: var(--step-1); }

  /* ================================================================================ the Wall */
  .wall-room .dialog__head {
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
    padding-inline-start: var(--margin);
    border-block-end: 1px solid var(--rule);
  }
  .wall-room .dialog__title { flex: 0 1 auto; display: flex; align-items: baseline; gap: 0.6em; }
  .wall-room__count {
    font: 450 var(--step--2)/1 var(--font-mono);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-2);
  }
  .wall-room__note { flex: 1 1 auto; margin: 0; font: 500 var(--step--1)/1.3 var(--font-ui); color: var(--ink-2); }
  .wall-room .dialog__body { display: flex; overflow: hidden; }
  /* One quiet 64 px bar: what is under the pointer (or how to move) on the left, the pad on the right. */
  .wall-room .dialog__foot {
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    min-block-size: 64px;
    padding: 10px var(--margin);
    background: var(--raised);
    box-shadow: var(--e1);
    border-block-start: 0;
  }

  .wall {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    min-block-size: 0;
    inline-size: 100%;
  }
  /* The wall itself: a touch darker than the page in Lamp light, the page's own wall in North light. */
  .wall__viewport {
    position: relative;
    flex: 1 1 auto;
    overflow: hidden;
    background: light-dark(var(--ground), #120d0a);
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    cursor: grab;
    contain: strict;
  }
  .wall[data-dragging] .wall__viewport { cursor: grabbing; }
  .wall__viewport:focus-visible { outline-offset: -4px; }
  .wall__grain {
    position: absolute;
    inset: -128px auto auto -128px;
    inline-size: calc(100% + 256px);
    block-size: calc(100% + 256px);
    background: var(--grain) repeat;
    background-position: 128px 128px;
    pointer-events: none;
    will-change: transform;
  }
  .wall__tiles { position: absolute; inset: 0; }
  /* The lamp pool behind the painting under the pointer or the keyboard: light on the wall round it,
     never over it (the tiles are above). --pool is transparent in North light and high contrast. */
  .wall__pool {
    --glow: 80px;
    position: absolute;
    inset: 0 auto auto 0;
    border-radius: 18%;
    box-shadow:
      0 calc(var(--glow) * -0.18) calc(var(--glow) * 0.9) calc(var(--glow) * 0.42) var(--pool),
      0 calc(var(--glow) * -0.1) calc(var(--glow) * 0.45) calc(var(--glow) * 0.16) var(--pool);
    pointer-events: none;
    will-change: transform;
    transition: opacity var(--dur-settle) var(--ease-set);
  }
  .wall__pool[hidden] { display: block; opacity: 0; }
  .wall[data-dragging] .wall__pool { opacity: 0; }
  .wall__tile {
    position: absolute;
    inset: 0 auto auto 0;
    display: block;
    box-shadow: 0 1px 2px var(--hang-contact-color), 0 10px 22px -8px var(--hang-cast-color);
    -webkit-user-drag: none;
    will-change: transform;
  }
  .wall__tile > img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover; /* the box has the image's own ratio: nothing is cropped */
    pointer-events: none;
  }
  /* The keyboard frame: two-tone (lamp ring over a wall-coloured band), so it reads on any painting. */
  .wall__frame {
    position: absolute;
    inset: 0 auto auto 0;
    outline: 2px solid var(--lamp);
    outline-offset: 3px;
    box-shadow: 0 0 0 3px var(--ground), 0 0 0 7px var(--ground);
    pointer-events: none;
    will-change: transform;
  }
  .wall__frame[hidden] { display: none; }
  /* The torch (Lamp light, Full motion): shade outside the beam, never more than 30% (paintings never
     drop below 70%). A pool twice the size of the view, drawn once and moved on the compositor. */
  .wall__torch {
    position: absolute;
    inset: 0 auto auto 0;
    display: none;
    background: radial-gradient(closest-side circle,
      rgb(0 0 0 / 0) 0,
      rgb(0 0 0 / 0) 16%,
      rgb(0 0 0 / 0.07) 26%,
      rgb(0 0 0 / 0.18) 38%,
      rgb(0 0 0 / 0.27) 52%,
      rgb(0 0 0 / 0.3) 64%);
    pointer-events: none;
    will-change: transform;
  }
  .wall[data-torch="on"] .wall__torch { display: block; }
  /* Phase 3 (js/v3/gl/wall.js): the WebGL wall draws into a canvas inside the viewport before the
     frame (gl.css fades a host's direct child; this one sits a level deeper). Once it is live
     (data-renderer="gl", set by justified.js) the DOM tiles stay as invisible hit targets (hover
     labels, clicks, the keyboard frame) and the CSS torch and pool give way to the shader's, after
     the canvas's 180 ms fade so the wall never shows bare. A tile being opened shows again (under
     the canvas) so the walk-up morph has its image. The shader's light is its own (a tighter torch
     beam, shadows cast away from it, a warm pool): the CSS torch and pool are the DOM wall's. */
  .wall[data-gl-state="live"] .wall__viewport > .gl-canvas { opacity: 1; }
  .wall[data-renderer="gl"] .wall__tile { opacity: 0; transition: opacity 0s linear 180ms; }
  .wall[data-renderer="gl"] .wall__tile[data-picked] { opacity: 1; transition: none; }
  /* A phone zoomed in: the canvas cuts this painting out and the tile's own image shows through
     (the canvas draws its shadows, so the tile casts none of its own). */
  .wall[data-renderer="gl"] .wall__tile[data-sharp] { opacity: 1; transition: none; box-shadow: none; }
  .wall[data-renderer="gl"] :is(.wall__torch, .wall__pool) { visibility: hidden; transition: visibility 0s linear 180ms; }
  /* The accessible twin: links in wall order, read and focused but not drawn (the frame shows focus). */
  .wall__list {
    position: absolute !important;
    inline-size: 1px;
    block-size: 1px;
    margin: 0;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    list-style: none;
  }

  .wall__info {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    gap: var(--space-4);
    min-inline-size: 0;
  }
  /* The label reads on one line: title, then the catalogue line, then "6 of 38". */
  .wall__label {
    --label-size: var(--step-1);
    display: flex;
    align-items: baseline;
    gap: 0 var(--space-4);
    flex: 0 1 auto;
    min-inline-size: 0;
    margin: 0;
    white-space: nowrap;
  }
  .wall__label .label__title { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; line-height: 1.3; }
  .wall__label .label__title:empty { display: none; }
  .wall__label :is(.label__meta, .label__extra) { flex: none; }
  .wall__label .label__extra { font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: 0.04em; }
  .wall__label[data-empty] .label__extra { font-family: var(--font-ui); font-size: var(--step--1); letter-spacing: 0; }
  .wall__label .label__extra:empty { display: none; }
  .wall__help { flex: 0 1 auto; min-inline-size: 0; margin: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--step--1); color: var(--ink-2); }
  .wall__info[data-state="label"] .wall__help { display: none; }
  .wall__pad {
    flex: none;
    --pad-space: var(--space-3);
    grid-template-columns: 44px 44px var(--pad-space) repeat(4, 44px) var(--pad-space) 44px;
    grid-template-rows: 44px;
    grid-template-areas: "zo zi . left up down right . centre";
    box-shadow: none;
    background: transparent;
    padding: 0;
  }
  .wall__pad .button--icon { --_bd: var(--rule); }
  .wall__pad .button--icon:hover { --_bd: var(--edge); }
  .wall__arrow--left { rotate: 180deg; }
  .wall__arrow--up { rotate: -90deg; }
  .wall__arrow--down { rotate: 90deg; }
  .wall__dot { inline-size: 6px; block-size: 6px; background: currentColor; border-radius: 1px; }

  /* Phones: the label above, the pad below (seven 44 px targets fill the width). */
  @media (max-width: 599.98px) {
    .wall-room__note { flex-basis: 100%; order: 3; padding-block-end: var(--space-2); }
    .wall-room .dialog__foot { flex-wrap: wrap; justify-content: center; padding-block: var(--space-2); gap: var(--space-2); }
    .wall__info { flex-basis: 100%; }
    .wall__help { display: none; }
    .wall__label { --label-size: var(--step-0); flex-wrap: wrap; white-space: normal; }
    .wall__label .label__title { flex-basis: 100%; white-space: nowrap; }
    .wall__pad { --pad-space: 4px; }
  }
  @media (max-height: 560px) {
    .wall__help { display: none; }
  }

  @media (forced-colors: active) {
    .wall__torch, .wall__grain { display: none !important; }
    .wall__frame { outline-color: Highlight; box-shadow: none; }
    .wall__tile { box-shadow: none; outline: 1px solid CanvasText; }
    .facet-trigger { border-color: ButtonText; }
    .facet-trigger__n { forced-color-adjust: none; background: CanvasText; color: Canvas; }
    .ptile::after { display: none; }
  }
  @media (prefers-contrast: more) {
    .wall__torch, .wall__grain { display: none !important; }
  }
}
