/* The guide's own layer over the Classical design system.
   Contrast overrides first, then the components the system does not carry:
   the chip, the timeline row and its markers, the plate, the detail sheet.

   The guide is dark only. A gallery is a dark room with lit walls, and the
   plates carry the light; a paper-white page beside them reads as a leak. */

:root {
  --color-bg: #100f0e;
  --color-surface: #1c1a19;
  --color-text: #f5f2ec;
  --color-divider: color-mix(in srgb, #f5f2ec 30%, transparent);
  --color-accent: #d9a75f;
  --color-accent-700: #e7bd7e;
  --color-accent-600: #dfae68;
  --color-accent-100: #2a231a;
  --color-accent-200: #3a2f21;
  --color-neutral-100: #201e1c;
  --color-neutral-200: #2b2926;
  --color-neutral-300: #3a3733;
  --color-neutral-700: #a8a29a;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / .5);
  --shadow-md: 0 3px 10px rgb(0 0 0 / .55);

  --dim: .32;
  /* The gap the connector opens above every entry on a phone. */
  --connector: 34px;
  /* Every entry opens on a label or on the walk line, both 14.5px on the body's
     1.55 leading. Half of this is how far the marker sits into its entry. */
  --label-line: 22.5px;
  /* Cormorant SC — a family of its own, because Cormorant Garamond ships no
     `smcp` and `font-variant-caps` would only synthesise shrunken capitals. */
  --font-smallcaps: "Cormorant SC", var(--font-heading);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--color-bg);
  color: var(--color-text);
}

body {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  min-height: 100vh;
}

/* Buttons speak at the secondary size; the quiet ones one step down. */
.btn { font-size: 14.5px; }
.btn-ghost { font-size: 12.5px; }

a { color: var(--color-accent-700); text-underline-offset: 2px; }
a:hover { color: var(--color-accent); }

/* Labels are set in real small capitals, not in transformed capitals: the copy
   keeps its own capitalisation and the font supplies the shapes. Small caps
   need less tracking than full capitals, and two steps more size to hold the
   same weight on the page: their letters stand at 468/1000 against a cap
   height of 625, so at the label sizes the old transformed capitals used, the
   capital that opens each label towers over the rest of it. */
.kicker {
  font-family: var(--font-smallcaps);
  font-weight: 400;
  font-feature-settings: 'tnum';
  letter-spacing: .09em;
  font-size: 14.5px;
}

.muted { color: color-mix(in srgb, var(--color-text) 82%, transparent); }
.quiet { color: color-mix(in srgb, var(--color-text) 74%, transparent); }

/* — chips: every option control in the setup view — */

.chip {
  font: inherit;
  font-size: 14.5px;
  padding: 7px 12px;
  min-height: 44px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}

.chip:hover { background: color-mix(in srgb, var(--color-text) 6%, transparent); }

.chip[aria-pressed="true"] {
  border-color: var(--color-accent);
  color: var(--color-accent-700);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.chip:focus-visible, button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.chip-centred { text-align: center; font-feature-settings: 'tnum'; }

.chip-wide {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  width: 100%;
}

.chip-note { font-size: 12.5px; opacity: .82; text-align: right; }

/* — setup — */

.setup { max-width: 560px; margin: 0 auto; padding: 32px 20px 0; }

.setup-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.setup h1 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 37px;
  line-height: 1.08;
  letter-spacing: normal;
  margin: 14px 0 8px;
}

.setup-intro {
  margin: 0;
  font-size: 16.5px;
  color: color-mix(in srgb, var(--color-text) 86%, transparent);
  text-wrap: pretty;
}

/* Same treatment as .kicker — one label size everywhere, distinguished by the
   space around it rather than by a size nobody can measure by eye. */
.section-label {
  font-family: var(--font-smallcaps);
  font-size: 14.5px;
  letter-spacing: .09em;
  margin: 26px 0 10px;
}

/* The two flows, named side by side directly under the title. Whichever is
   pressed, the body below it is that flow and nothing of the other one is on the
   screen — which is the whole reason the switch is here rather than folded into
   the constraints as another chip. */
.mode-switch {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin: 16px 0 4px;
}

/* The two stand the same height because they are a pair, but the note follows
   its own label rather than being pushed to the floor of the taller one. */
.chip-mode {
  display: grid;
  gap: 2px;
  align-content: start;
  justify-items: start;
  text-align: left;
  padding: 9px 12px;
}

.chip-mode .chip-note { text-align: left; }

.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.stack { display: grid; gap: 8px; }

.setup .btn-primary {
  margin-top: 30px;
  min-height: 48px;
  font-size: 16.5px;
  font-family: var(--font-heading);
  font-weight: 400;
}

.preview { margin: 12px 0 0; font-size: 12.5px; text-align: center; }
.hint { margin: 10px 0 0; font-size: 12.5px; }

/* The one reading in the picking flow that judges rather than counts, so it sits
   against the chips that set the time and carries the running voice, not the
   hint's. It is gold only when the picks have outgrown the time. */
.pick-against { margin: 12px 0 0; font-size: 14.5px; text-wrap: pretty; }
.pick-against[data-over="true"] { color: var(--color-accent-700); }

/* — the contact sheet: every curated work, dimmed when the plan misses it — */

/* The form is a column; the sheet is a wall, and takes whatever width the window
   has once the constraints above it have stopped needing any. */
.collection-block { max-width: 560px; margin: 0 auto; padding: 0 20px 56px; }
.collection-rule { margin-top: 44px; }

/* `--plate-h` is the height every plate hangs within, and so the height of a row
   of them; the columns are as many as fit at that scale. */
.collection {
  --plate-h: 96px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 24px 14px;
  margin-top: 18px;
}

/* The tile is a cell holding two controls, because the verb changes with the
   flow and a button cannot hold another button: the picture means read in the
   one flow and pick in the other, and the caption under it always reads. Neither
   of them is drawn as a control — the wall is a wall of pictures. */
.tile { text-align: center; transition: opacity .12s linear; }

.tile-face, .tile-caption {
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: center;
  cursor: pointer;
}

/* Dimming means something different in each flow, so the rule is keyed on the
   flow. Guided: the same dimming the line uses for what is not being read, doing
   the same job — what the current constraints leave out is still there, just not
   lit. Picking: nothing is dimmed for being unpicked, because ninety-odd dim
   plates are a wall nobody can read, and only what can never be walked to is. */
.screen[data-mode="guided"] .tile[data-lit="false"] { opacity: var(--dim); }
.screen[data-mode="guided"] .tile[data-lit="false"]:hover { opacity: .62; }
.screen[data-mode="picked"] .tile[data-reachable="false"] { opacity: var(--dim); }
.screen[data-mode="picked"] .tile[data-reachable="false"]:hover { opacity: .62; }

.tile-caption:hover .tile-title { color: var(--color-accent-700); }
.tile-face:disabled { cursor: default; }

/* A picked work is marked on the picture itself. An outline hugs the plate at
   whatever proportions the work has, which a badge in a corner cannot do — the
   plates here are anything from a miniature to a two-metre canvas. The pointer
   shows the same outline before the tap, faintly, so what a tap is about to do
   is legible without a word being printed for it. */
.screen[data-mode="picked"] .tile[data-picked="true"] .plate-wrap {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

.screen[data-mode="picked"] .tile[data-picked="false"][data-reachable="true"]
  .tile-face:hover .plate-wrap {
  outline: 2px solid color-mix(in srgb, var(--color-accent) 45%, transparent);
  outline-offset: 3px;
}

/* Its line is held open on every tile in the flow, whether or not the work is
   picked: the same reason two title lines are held open, which is that a row of
   plates has to keep standing on one line while it is being picked from. */
.tile-check {
  display: none;
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--color-accent-700);
}

.screen[data-mode="picked"] .tile-check { display: block; visibility: hidden; }
.screen[data-mode="picked"] .tile[data-picked="true"] .tile-check { visibility: visible; }


/* Nothing is cropped to tidy the grid: each plate is fitted inside a band of one
   height and hung on its floor, so the works keep their own proportions and a
   row still stands on one line with its captions the same distance below it. */
.plate-band {
  display: grid;
  height: var(--plate-h);
  align-items: end;
  justify-items: center;
}

/* Wide enough for the band's full height, or for the column, whichever comes
   first; the window's own proportions take the height from there. */
.plate-band .plate-wrap {
  margin-top: 0;
  width: min(100%, var(--plate-h) * var(--crop-ratio));
}

/* Two lines are held open whether the title needs them or not, so a long title
   cannot push its own row of captions out of line with the others. */
.tile-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  min-height: calc(2 * 1.3 * 12.5px);
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.3;
  text-wrap: pretty;
}

/* A phone column has no room for a byline under a 96px plate; a wall has. */
.tile-by {
  display: none;
  font-size: 12.5px;
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Said for a screen reader, which has no dimming to read. */
.tile-state {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The constraints stop needing width long before the plates do. */
@media (min-width: 720px) {
  .collection-block { max-width: 1120px; padding: 0 28px 76px; }

  .collection {
    --plate-h: 150px;
    grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
    gap: 34px 22px;
  }

  .tile-by { display: block; }
}

/* — the count under the picking wall — */

/* The mirror of the tour's own bar: that one sticks to the top of the line, this
   one to the foot of the wall, because picking happens while scrolling a hundred
   plates and the count and the way out have to stay in reach of the thumb. It is
   drawn only in the flow that has anything to count. */
.pick-bar { display: none; }

.screen[data-mode="picked"] .pick-bar {
  display: block;
  position: sticky;
  bottom: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--color-bg) 93%, transparent);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--color-divider);
}

.pick-row {
  max-width: 1120px;
  margin: 0 auto;
  padding: 10px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.pick-count {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pick-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.pick-start:disabled { opacity: .45; cursor: default; }

/* The count is the reading that can be cut; the two controls cannot. */
@media (max-width: 389px) {
  .pick-row { padding: 10px 14px; gap: 8px; }
  .pick-count { font-size: 12.5px; }
}

/* — the line — */

.chrome {
  position: sticky;
  top: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--color-bg) 93%, transparent);
  backdrop-filter: blur(8px);
  transition: transform .16s linear;
}

.chrome[data-hidden="true"] { transform: translateY(-105%); }

/* Four readings share this row, and they are all labels: the bar carries the
   label voice once and every one of them inherits it, so none has a size, a
   family or a colour of its own. */
.chrome-row {
  max-width: 620px;
  margin: 0 auto;
  padding: 6px 18px 7px;
  display: flex;
  align-items: baseline;
  gap: 12px;
}

.chrome-at { white-space: nowrap; }

.chrome-nudge {
  flex: 1;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chrome-nudge[data-behind="true"] { color: var(--color-accent-700); }

/* One voice is a wider voice, and four readings no longer fit a phone row. The
   clock is the one the visitor can read anywhere else — the phone shows the time
   in its own status bar, and the nudge names the finishing time itself — so it
   waits for a window with room for it. */
.chrome-clock { display: none; white-space: nowrap; }

/* Standing a little clear of the nudge, which names a time of its own: in one
   voice the two readings no longer tell themselves apart by their typeface. */
@media (min-width: 480px) {
  .chrome-clock { display: inline; margin-left: 6px; }
}

/* The one way back to the setup screen, so it is reachable from anywhere on the
   line rather than only from the Atrium the visitor has already walked past. A
   button brings its own family and size, so it is the one thing in the row that
   has to be told to inherit. The rule beside it is what separates the readings
   from the one control: its gold is the text gold, and the nudge turns the same
   gold when the visit runs late. */
.chrome-edit {
  font-family: inherit;
  font-size: inherit;
  letter-spacing: inherit;
  color: var(--color-accent-700);
  border-left-color: var(--color-divider);
  padding: 0 0 0 12px;
  white-space: nowrap;
}

/* Whatever is left over on a narrow phone goes to the nudge, the counter
   included: the progress rule under the bar and the head of the stop itself both
   say where the visit has got to, and nothing else says the sentence. */
@media (max-width: 389px) {
  .chrome-row { gap: 8px; }
  .chrome-at { display: none; }
}

.progress { height: 1px; background: var(--color-divider); position: relative; }
.progress > i { position: absolute; inset: 0 auto 0 0; background: var(--color-accent); }

.line { max-width: 620px; margin: 0 auto; padding: 0 18px 40px; }

/* The line, on a phone, runs inside the column and survives in the gaps between
   entries. Each row opens a connector above its content, the segment descends
   through it, and the marker ends it level with the entry's first line. From
   the tablet breakpoint up the column is centred in the viewport on its own, so
   the rail runs continuously to the left of the text. `--axis` is the horizontal
   line the markers sit on; `--mark-y` is where the marker's centre falls inside
   its own row.

   The axis stands 26px off the right edge of the column, the mirror of the rail
   above the breakpoint: everything sharing a line with a marker — a stop's label
   and its minutes, a walk's sentence — is one run of text to the left of it. */
.row {
  --axis: calc(100% - 26px);
  /* How far text on a marker's own line may run before it reaches the axis. */
  --text-limit: calc(var(--axis) - 16px);
  --mark-y: calc(var(--connector) + var(--entry-top, 0px) + var(--label-line) / 2);
  position: relative;
  padding-top: var(--connector);
}

/* The line descends through the gap and meets the marker's edge, which stands
   level with the first line of the entry it belongs to — the way the left rail
   marks its stops above the breakpoint. It ends on the edge rather than running
   under the marker, so every kind of marker is joined to the line the same way
   and none of them needs a backing plate to hide an overshoot. */
.rail {
  position: absolute;
  left: var(--axis);
  translate: -50% 0;
  top: 0;
  height: calc(var(--mark-y) - var(--mark-h, var(--mark)) / 2);
  width: 1px;
  background: var(--color-divider);
}

/* Nothing precedes the Atrium, so the first connector would dangle. */
.line > .row:first-child > .rail { display: none; }

/* The entries that stand between two artworks — a walk, a break, a floor header
   — carry the line through: they are held clear of the axis, the rail runs the
   row's whole height, and the marker sits on the line at the entry's own first
   line, the way it does above the breakpoint. The floor plan is drawn to its own
   `max-width` and centred, so holding its card back leaves it its size.

   The line therefore breaks where a painting hangs: a stop's plate runs to the
   column's edge, and its rail ends on the marker above it. It ends at the Atrium
   and at the exit, where the visit does. */
.row-walk > .rail, .row-break > .rail, .row-floor > .rail {
  top: 0;
  bottom: 0;
  height: auto;
}

.entry-walk, .entry-break, .entry-floor { max-width: var(--text-limit); }

/* A break and a floor header dim with the card they head, and the rail runs
   past them, so both take the opaque backing behind the mark. A walk dims like
   a card, and the rail runs its whole height, so it takes the backing too. */
.row-break > .mark-back, .row-floor > .mark-back, .row-walk > .mark-back { display: block; }

/* `--mark` is the marker's width and `--mark-h` its height, which differ only
   for the floor rule. Above the breakpoint the rail runs the whole height of the
   row and passes behind the marker, so there a second, opaque layer masks it —
   only the mark dims, and the rail never shows through a dimmed dot. */
.mark, .mark-back {
  position: absolute;
  left: var(--axis);
  top: var(--mark-y);
  translate: -50% -50%;
  width: var(--mark);
  height: var(--mark-h, var(--mark));
}

.mark-back { display: none; width: var(--back); height: var(--back); background: var(--color-bg); }
.mark { transition: opacity .12s linear; }

.row-stop { --mark: 15px; --back: 23px; }
.row-walk { --mark: 9px; --back: 17px; }
.row-break { --mark: 13px; --back: 21px; }
.row-terminus { --mark: 17px; --back: 25px; }
.row-floor { --mark: 15px; --mark-h: 1px; --back: 15px; }

.row-stop > .mark, .row-stop > .mark-back,
.row-walk > .mark,
.row-terminus > .mark, .row-terminus > .mark-back { border-radius: 50%; }

.row-stop > .mark { background: var(--color-accent); }
.row-walk > .mark { background: var(--color-bg); border: 1px solid var(--color-divider); }
.row-break > .mark, .row-terminus > .mark {
  background: var(--color-bg);
  border: 1px solid var(--color-accent);
}

/* The floor marker is a rule across the line, not a point on it. */
.row-floor > .mark { background: var(--color-divider); }
.row-floor > .mark-back { height: 9px; }

.card { transition: opacity .12s linear; border: 0; padding: 0; gap: 0; border-radius: 0; }
.card[data-lit="false"], .mark[data-lit="false"], .entry-walk[data-lit="false"] { opacity: var(--dim); }

/* On a phone the connector carries all the space above an entry. Above the
   breakpoint the entry pads itself instead, and `--entry-top` is that padding —
   one value, so the marker cannot drift away from the line it belongs to. */
.entry-stop, .entry-floor, .entry-walk, .entry-break, .entry-term {
  padding-top: var(--entry-top, 0px);
}

.entry-stop { padding-bottom: 22px; cursor: pointer; display: block; width: 100%;
  text-align: left; background: none; color: inherit; font: inherit; }
.entry-floor { padding-bottom: 6px; }
/* A transition sits between two entries and takes the same whitespace on both
   sides of itself — the wider of the two, which is the one above. */
.entry-walk { padding-bottom: 22px; }
.entry-break { padding-bottom: 14px; }
.entry-term { padding-bottom: 22px; }

/* Wide enough for the column to be centred in the viewport on its own: the line
   straightens out to the left of the text, runs the whole height of the page,
   and needs no gap opened above each entry to show through. */
@media (min-width: 640px) {
  /* The rail runs beside the text here, so nothing is held short of the axis. */
  .row { --axis: 15.5px; --text-limit: none; --connector: 0px; padding-left: 46px; }
  .rail { top: 0; bottom: 0; height: auto; }
  .mark-back { display: block; }
  .line > .row:first-child > .rail { display: block; }

  .row-stop { --entry-top: 8px; }
  .row-walk, .row-break { --entry-top: 14px; }
  /* 22 above the walk plus its own 14, against the next entry's 8 below. */
  .entry-walk { padding-bottom: 28px; }
  .row-terminus { --entry-top: 22px; }
  .row-floor { --entry-top: 26px; }
}

/* The head runs from the left margin to the axis, with the stay at its right
   end, so both halves of it stand on the same side of the marker and the room
   code is spaced against the stay alone: at 320px `Stop 12 · Room 2.30.3` still
   holds one line. */
.stop-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  max-width: var(--text-limit);
}

.stop-head .where { color: var(--color-accent-700); }
.stop-head .stay { opacity: .75; white-space: nowrap; }

/* The window the work is seen through. It stands in the proportions of the work
   rather than of the photograph, and the photograph is laid behind it at the
   size that brings the work up to the opening — the whole picture where nothing
   was cropped, since the crop then reads 0 0 1 1 and every figure below comes
   out at its plain value. `plate.js` sets the four numbers per work. */
.plate-wrap {
  margin-top: 17px;
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: var(--crop-ratio);
}

/* What the plate and the parts of the work its description names share: one box,
   so a region given as a fraction of the work lands where the work is. Below the
   two-column breakpoint it is an empty wrapper and the hotspots are not drawn.
   The four numbers are the veil's, and stand at the whole work until a block of
   prose is hovered and `regions.js` narrows them. */
.plate-frame {
  position: relative;
  --region-x: 0;
  --region-y: 0;
  --region-w: 1;
  --region-h: 1;
}

.plate-regions { display: none; }

/* The design system mats its plates. Here the painting already carries its own
   frame, painted or gilt, and a second one drawn in CSS reads as a mistake. The
   mat was also holding the plate off the text around it, so the space it took
   moves out into the margins rather than disappearing with it. */
.plate {
  position: absolute;
  top: calc(-100% * var(--crop-y) / var(--crop-h));
  left: calc(-100% * var(--crop-x) / var(--crop-w));
  width: calc(100% / var(--crop-w));
  height: calc(100% / var(--crop-h));

  /* The photograph is wider than its window whenever a border is clipped, and
     the design system's `img { max-width: 100% }` would pull it back to fit. */
  max-width: none;
  border: 0;
  outline: 0;
}

.entry-stop h2 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 29px;
  line-height: 1.12;
  letter-spacing: normal;
  text-wrap: balance;
  margin: 21px 0 2px;
}

.byline { font-size: 14.5px; font-style: italic; }

.body-text {
  text-align: justify;
  hyphens: auto;
  margin: 12px 0 0;
  font-size: 16.5px;
}

.aside { margin-top: 14px; border-top: 1px solid var(--color-divider); padding-top: 10px; }
.aside .label { color: var(--color-accent-700); margin-right: 8px; }
.aside .text { font-size: 14.5px; font-style: italic; text-wrap: pretty; }

.ask {
  margin-top: 12px;
  border: 1px solid var(--color-divider);
  border-left: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}

.ask .label { color: var(--color-accent-700); margin-right: 8px; }
.ask .text { font-size: 14.5px; }

.affordance {
  margin-top: 14px;
  color: var(--color-accent-700);
  border-bottom: 1px solid var(--color-accent);
  display: inline-block;
  padding-bottom: 2px;
}

.walk-line { font-size: 14.5px; display: flex; gap: 10px; align-items: baseline; }
.walk-line .mins { white-space: nowrap; }
.walk-line .what { text-wrap: pretty; }

.floor-title, .term-title, .break-title {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.12;
  text-wrap: balance;
  margin-top: 2px;
}

/* Stops and termini are the content; floors and breaks divide it. Two sizes,
   not four — a 27/29/30 spread reads as imprecision, not as hierarchy. */
.entry-term .term-title { font-size: 29px; }
.floor-title, .break-title { font-size: 22px; }

.entry-term .kicker, .entry-floor .kicker, .entry-break .kicker {
  color: var(--color-accent-700);
}

.term-text, .break-text { font-size: 14.5px; margin-top: 6px; text-wrap: pretty; }

.plan { margin-top: 12px; }
.plan svg { display: block; width: 100%; max-width: 300px; margin: 0 auto; height: auto; }
.plan-caption {
  font-size: 12.5px;
  font-style: italic;
  margin-top: 9px;
  text-wrap: pretty;
}

.actions { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.selection { margin-top: 14px; border-top: 1px solid var(--color-divider);
  padding-top: 10px; font-size: 14.5px; }
/* The second line is only ever there when a hand-picked walk runs past the time
   asked for, and that is worth being seen rather than merely printed. */
.selection > div + div { margin-top: 2px; color: var(--color-accent-700); }

/* — detail sheet — */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--color-bg);
  overflow-y: auto;
  overscroll-behavior: contain;

  /* One reading column, head and body on the same measure, until the window is
     wide enough for the plate to have a column of its own. */
  --sheet-width: 620px;
  /* The height of the sticky head, which is what the plate below it hangs from:
     one 14.5px label on the body's 1.55 leading, its padding and its rule. */
  --sheet-head: 36px;
}

.sheet-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-divider);
}

.sheet-head > div {
  max-width: var(--sheet-width);
  margin: 0 auto;
  padding: 6px 18px 7px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.sheet-head .kicker { color: var(--color-accent-700); white-space: nowrap; }

/* The switch stands at the end of the head, on the way back's own side of it and
   parted from it the way the room is parted from the floor. It is drawn only
   where there is something for it to switch — the links run on the two-column
   sheet and on pointers that hover, and nowhere else. */
.sheet-head-end { display: flex; align-items: center; gap: 9px; }
.sheet-head-dot { display: none; color: var(--color-divider); }
.sheet-regions { display: none; padding: 0; gap: 7px; white-space: nowrap; }
.sheet-regions[aria-pressed="false"] { color: color-mix(in srgb, var(--color-text) 62%, transparent); }

/* A framed square: the frame is always there, and a filled square settles
   inside it when the links are on. Both are drawn in the button's own colour,
   so the mark says the same thing the label does and there is one state to keep
   in step. */
.sheet-regions .switch {
  position: relative;
  width: 12px;
  height: 12px;
  border: 1px solid currentColor;
}

.sheet-regions .switch::after {
  content: '';
  position: absolute;
  inset: 2px;
  background: currentColor;
  opacity: 0;
  transition: opacity 160ms ease;
}

.sheet-regions[aria-pressed="true"] .switch::after { opacity: 1; }

.sheet-body { max-width: var(--sheet-width); margin: 0 auto; padding: 20px 18px 72px; }

.sheet-body h2 {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 37px;
  line-height: 1.08;
  letter-spacing: normal;
  text-wrap: balance;
  margin: 25px 0 4px;
}

.sheet-body .section-label { margin-top: 34px; }
.sheet-body p { text-align: justify; hyphens: auto; font-size: 16.5px; margin: 14px 0 0; }

/* The table is a change of register from the prose above it, not a continuation
   of the list, and needs the distance to say so. */
.facts { margin-top: 40px; border-top: 1px solid var(--color-divider); }

.fact {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-divider);
  font-size: 14.5px;
}

.fact .k { color: var(--color-accent-700); padding-top: 3px; white-space: nowrap; }
.fact .v { text-align: right; }

/* Numbers hang in the page margin, so the points read as a list rather than as
   a second version of the table of facts below them. */
.look { list-style: decimal outside; padding-inline-start: 0; margin: 0;
  font-size: 16.5px; }
.look li { margin-top: 11px; }
.look li::marker { font-family: var(--font-heading);
  font-variant-numeric: oldstyle-nums; color: var(--color-accent-700); }

.sheet-body .btn-primary { margin-top: 26px; min-height: 46px;
  font-family: var(--font-heading); font-weight: 400; font-size: 14.5px; }

.provenance { margin-top: 26px; font-size: 12.5px; }
.provenance a { overflow-wrap: anywhere; }

/* The sheet is the one place in the guide where the work is looked at rather
   than walked past, and on a wide window the reading column is the wrong size
   for looking. Past this width the plate takes a column of its own and stands
   as tall as the window under the head allows; the text runs beside it at the
   same measure it always had. The plate is sticky, so the description scrolls
   past a work that stays whole and in view — the reason for the split.

   The text column is capped and the plate takes the rest, so widening the
   window widens the picture. The breakpoint is where what is left over is at
   least the width of the single column the plate came out of. */
@media (min-width: 1160px) {
  .sheet {
    --sheet-width: 1400px;
    --gutter: 28px;
    --column-gap: 40px;
    /* The air above the plate, and below it at the foot of the window. */
    --sheet-air: 24px;
  }

  .sheet-head > div { padding-inline: var(--gutter); }

  /* Both columns are the full height of the taller one — the plate's column has
     to run the length of the text for the plate to have anywhere to stick. */
  .sheet-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(320px, 460px);
    gap: 0 var(--column-gap);
    padding: var(--sheet-air) var(--gutter) 0;
  }

  /* The tail of the page belongs to the text, not to the grid: a row that ends
     where the reading ends is a row the plate stays stuck to all the way down. */
  .sheet-text { padding-bottom: 72px; }

  /* What is left of the window under the head, less the air above and below. */
  .sheet-plate {
    --plate-height: calc(100dvh - var(--sheet-head) - 2 * var(--sheet-air));
  }

  /* The frame is what sticks, inside a column as tall as the text beside it. It
     sticks where it already stands, so it does not move at all: the work is hung
     once and the description is read past it. Height-led, like the tiles on the
     contact sheet — the width is read back off the proportions of the work, so
     the plate never outgrows the window. The plate fills the frame; what else is
     in there travels with it. */
  .sheet-plate .plate-frame {
    position: sticky;
    top: calc(var(--sheet-head) + var(--sheet-air));
    margin: 0 auto;
    width: min(100%, var(--plate-height) * var(--crop-ratio));
  }

  .sheet-plate .plate-wrap { margin-top: 0; }

  /* The title stands level with the top of the plate beside it. */
  .sheet-text > h2:first-child { margin-top: 0; }
}

/* — the description and the place it names —

   A block of prose that names a part of the work is joined to that part: hover
   the sentence and the rest of the painting falls away behind a veil, hover the
   part and the sentence takes the text gold. `regions.js` moves the light; this
   is only what the light looks like.

   Gated to the two-column sheet, where the work stands beside the description
   and stays in view while it scrolls, and to pointers that can hover. On a phone
   the plate is above the text rather than beside it, so dimming it would work on
   something already off the screen.

   Gated again on the sheet's own switch, and that gate is this whole block: with
   the links off there is no rule under the prose, no veil, and no hotspot to hit
   — the sheet is the sheet it was before any of this. */
@media (min-width: 1160px) and (hover: hover) {
  .sheet-regions { display: inline-flex; }
  .sheet-head-dot { display: inline; }

  .sheet[data-regions="on"] .plate-regions {
    display: block;
    position: absolute;
    inset: 0;
  }

  /* Nothing is drawn: the hotspot is a hit area over the part of the work its
     sentence is about, in the fractions of the work `plate.js` hangs the whole
     photograph by. */
  .plate-region {
    position: absolute;
    left: calc(var(--region-x) * 100%);
    top: calc(var(--region-y) * 100%);
    width: calc(var(--region-w) * 100%);
    height: calc(var(--region-h) * 100%);
  }

  /* The veil, with a hole cut in its mask where the region is: the work keeps
     its full strength there and everything else falls away behind it. The
     softness is the gradient's own, so there is no edge to read as a box drawn
     on a painting, and the percentages resolve against the frame, so it holds at
     every width the plate is drawn at. A pseudo-element because it must never be
     a hit target — the hotspots lie underneath it. */
  .plate-frame::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: color-mix(in srgb, var(--color-bg) 58%, transparent);
    opacity: 0;
    transition: opacity 220ms ease;
    mask-image: radial-gradient(ellipse calc(var(--region-w) * 70%)
                                        calc(var(--region-h) * 70%)
                                at calc((var(--region-x) + var(--region-w) / 2) * 100%)
                                   calc((var(--region-y) + var(--region-h) / 2) * 100%),
                                transparent 0 58%, #000 100%);
  }

  .sheet[data-regions="on"] .plate-frame[data-lit="true"]::after { opacity: 1; }

  /* Everything anchored is ruled underneath, so what points at the work can be
     found without hovering the page to look for it: a dotted rule in a gold too
     faint to read as a link, which comes up to the text's own gold when it
     lights. Justification clones a marked phrase that runs over a line break,
     and each piece carries the rule, so it breaks the way the words do.

     The colours are settled here and the switch only draws the line, because
     `text-decoration-line` is not animatable and the colour is: gating the
     colour instead would run the transition on the way in, and the rule would
     arrive in the text's own white and fade back to gold. */
  .sheet-text [data-region] {
    text-decoration: underline dotted;
    text-decoration-line: none;
    text-decoration-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
    text-underline-offset: 3px;
    transition: color 220ms ease, text-decoration-color 220ms ease;
  }

  .sheet[data-regions="on"] .sheet-text [data-region] { text-decoration-line: underline; }

  /* Where both directions end: the words take the text gold. */
  .sheet[data-regions="on"] .sheet-text [data-region][data-lit="true"] {
    color: var(--color-accent-700);
    text-decoration-color: var(--color-accent-700);
  }
}
