/* The Many Erics: exhibition identity outside, quiet galleries inside. */

:root {
  --ink: #111111;
  --ink-soft: #3b3b3b;
  --paper: #ffffff;
  --signal: #ffe500;
  --floor: #b4b8bd;
  --floor-edge: #9ea3a9;

  /* Archivo carries the display voice (condensed caps) and artwork titles (italic).
     Instrument Sans carries everything else. */
  --display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font: "Instrument Sans", "Helvetica Neue", Arial, sans-serif;

  --topbar-h: 64px;
  --floor-h: clamp(100px, 15vh, 140px);
  --wall-h: calc(100dvh - var(--floor-h));
  --hang-h: min(58vh, 720px);
  --label-w: 270px;
  --gutter: 40px;
  --bay-gap: clamp(120px, 14vw, 260px);
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p { margin: 0; }

/* Display type and artwork titles stay in Archivo. */
.entrance-title, .room-name, .exit-title, .plan-tip-name, .index-title,
.label-title, .index-work-title { font-family: var(--display); }
a { color: inherit; }
button { font: inherit; color: inherit; }
img { display: block; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

.skip-link {
  position: fixed; left: var(--gutter); top: 12px; z-index: 50;
  background: var(--signal); padding: 8px 12px;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

.link-button {
  background: none; border: 0; padding: 0; cursor: pointer;
}

/* ---------- Top bar ---------- */

.topbar {
  position: fixed; inset: 0 0 auto 0; z-index: 20;
  height: var(--topbar-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--gutter);
  pointer-events: none;
}
.topbar > * { pointer-events: auto; }

.wordmark {
  font-family: var(--display);
  font-size: 20px; font-weight: 900; font-stretch: 62%; letter-spacing: 0.02em; text-transform: uppercase;
  text-decoration: none;
  transition: opacity 300ms ease;
}
body.at-entrance .wordmark { opacity: 0; pointer-events: none; }

.topnav { display: flex; gap: 32px; font-size: 14px; }
.topnav a, .topnav button { text-decoration: none; }
.topnav a:hover, .topnav button:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ---------- The walk ---------- */

.walk {
  position: fixed; inset: 0;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.walk::-webkit-scrollbar { display: none; }
.walk:focus { outline: none; }

.wall {
  position: relative;
  display: flex;
  height: 100dvh;
  width: max-content;
}

.rooms { display: flex; height: 100%; }

.entrance, .exit, .room { height: var(--wall-h); }

/* ---------- Entrance ---------- */

.entrance {
  width: max(72vw, 840px);
  background: var(--paper);
  padding: calc(var(--topbar-h) + 8px) var(--gutter) 32px;
  display: flex; flex-direction: column;
  container-type: inline-size;
}

.entrance-title {
  font-weight: 900;
  font-stretch: 62%;
  text-transform: uppercase;
  font-size: clamp(88px, 14.5vh, 200px);
  line-height: 0.84;
  letter-spacing: -0.01em;
}

.entrance-tagline {
  margin-top: 24px; padding-top: 14px;
  border-top: 2px solid var(--ink);
  font-size: 18px; font-weight: 500;
}

/* Tagline and content share one width, so the tagline's rule ends where the content does. */
.entrance-block { width: fit-content; max-width: 100%; --facts-gap: 32px; }

/* The note, audio guide and facts in one column. When the wall is wide enough, the way in
   sits in a second column on the facts' row, its top on the facts' rule. */
.entrance-main {
  margin-top: 28px;
  display: grid; grid-template-columns: minmax(0, 460px);
}
.entrance-body { display: contents; }
.entrance-body > * { grid-column: 1; justify-self: start; }
.entrance-body > .entrance-facts { justify-self: stretch; }
.entrance-intro { font-size: 15px; color: var(--ink-soft); }
.entrance-body .listen { margin-top: 18px; }

/* Exhibition facts, set like the details panel on a museum's exhibition page. */
.entrance-facts {
  margin: var(--facts-gap) 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--ink);
  display: flex; gap: 48px;
}
.entrance-facts dt {
  font-size: 12px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-soft);
}
.entrance-facts dd { margin: 4px 0 0; font-size: 18px; font-weight: 500; }

.entrance-foot {
  margin-top: var(--facts-gap);
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
}
@container (min-width: 760px) {
  .entrance-main { grid-template-columns: 460px auto; column-gap: 56px; }
  .entrance-foot { grid-column: 2; grid-row: 3; align-self: start; }
}
/* When the wall is too short for everything (walk.js checks), the facts step aside so the
   way in is never hidden under the floor. */
.entrance.is-compact .entrance-facts { display: none; }
.entrance.is-tight .walk-keys { display: none; }
.entrance.is-cramped .entrance-intro { display: none; }
.entrance.is-cramped .entrance-body .listen { margin-top: 0; }

/* Buttons: the entry and exit controls. Square, solid or outlined, like museum signage. */
.button {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 20px 14px;
  border: 1.5px solid var(--ink);
  background: transparent; color: var(--ink);
  font-size: 15px; font-weight: 600; line-height: 1; text-decoration: none;
  transition: background-color 150ms ease;
}
.button:hover { background: rgba(17, 17, 17, 0.06); }
.button--primary {
  background: var(--ink); color: var(--paper);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 10px 20px -12px rgba(0, 0, 0, 0.5);
}
.button--primary:hover { background: #333333; }
.button-arrow { font-size: 18px; line-height: 1; transition: transform 150ms ease; }
.button:hover .button-arrow--right { transform: translateX(4px); }
.button:hover .button-arrow--left { transform: translateX(-4px); }

/* While the visitor is still at the entrance, the arrow nudges toward the walk. */
@keyframes nudge {
  0%, 70%, 100% { transform: translateX(0); }
  80% { transform: translateX(5px); }
  90% { transform: translateX(1px); }
}
body.at-entrance .enter .button-arrow { animation: nudge 2.8s ease-in-out 1.2s infinite; }
body.at-entrance .enter:hover .button-arrow { animation: none; transform: translateX(4px); }

/* Keyboard hints */
.walk-keys { font-size: 13px; color: var(--ink-soft); }
kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 22px; padding: 0 6px;
  border: 1px solid rgba(17, 17, 17, 0.35); border-bottom-width: 2px; border-radius: 3px;
  background: rgba(255, 255, 255, 0.7);
  font: 600 12px/1 var(--font); color: var(--ink);
  vertical-align: 1px;
}

/* Hints that only make sense for a mouse and keyboard, or for touch. */
.coarse-only { display: none; }
@media (pointer: coarse) {
  .fine-only { display: none !important; }
  .coarse-only { display: inline; }
}

/* ---------- Rooms ---------- */

.room {
  position: relative;
  display: flex; align-items: center;
  gap: var(--bay-gap);
  padding: 0 var(--bay-gap) 0 clamp(80px, 9vw, 160px);
  /* A faint plaster overlay (light and shade only) gives the paint some surface without shifting its colour. */
  background: url("wall.webp") 0 0 / 768px 768px repeat, var(--wall);
  /* The seam between rooms reads as a doorway. */
  box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.06);
}
/* The polished floor below each room catches a faint reflection of its wall colour.
   The contact shadow is repeated on top so the reflection doesn't wash it out. */
.room::after {
  content: "";
  position: absolute; left: 0; right: 0; top: 100%;
  height: var(--floor-h);
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(0, 0, 0, 0.16), rgba(0, 0, 0, 0) 20px),
    linear-gradient(to bottom,
      color-mix(in srgb, var(--wall) 50%, transparent),
      color-mix(in srgb, var(--wall) 16%, transparent) 38%,
      transparent 75%);
}
/* A faint reflection of each work on the floor below it (positioned by walk.js).
   The box is flipped in place, so the artwork's lower edge sits nearest the wall.
   The image is squashed into 2.4 floor-heights to read as foreshortened, then blurred.
   The mask is written pre-flip: opaque at the box's bottom, which becomes its top. */
.reflection {
  position: absolute; top: calc(100% + 3px);
  height: var(--floor-h);
  z-index: 1;
  pointer-events: none;
  background-repeat: no-repeat;
  background-position: center bottom;
  background-size: 100% calc(var(--floor-h) * 2.4);
  transform: scaleY(-1);
  filter: blur(4px);
  opacity: 0.3;
  /* Fade toward the viewer, and feather the sides so it never reads as a box. */
  -webkit-mask-image:
    linear-gradient(to top, #000, transparent 80%),
    linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to top, #000, transparent 80%),
    linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  mask-composite: intersect;
}

/* The walls are so pale that a straight reflection only lightens the floor.
   Where supported, lift the reflection's chroma so the room's hue reads on the grey. */
@supports (color: oklch(from red l c h)) {
  .room::after {
    background:
      linear-gradient(to bottom, rgba(0, 0, 0, 0.16), rgba(0, 0, 0, 0) 20px),
      linear-gradient(to bottom,
        oklch(from var(--wall) calc(l * 0.97) calc(c * 3.5) h / 0.5),
        oklch(from var(--wall) calc(l * 0.97) calc(c * 3.5) h / 0.16) 38%,
        oklch(from var(--wall) l c h / 0) 75%);
  }
}

.room-intro {
  flex: none;
  width: 360px;
  padding-top: 24px;
  align-self: center;
}
.room-kicker {
  font-size: 13px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
}
.room-name {
  margin-top: 10px;
  font-size: 44px; line-height: 1.02; font-weight: 700; font-stretch: 75%;
}
.room-dates { margin-top: 12px; font-size: 16px; }
.room-text { margin-top: 20px; font-size: 15px; color: var(--ink-soft); }
.room-intro .listen { margin-top: 24px; }

.room--interregnum {
  width: 98vw;
  justify-content: center;
  padding: 0;
}
.room--interregnum .room-intro { width: 300px; }
.room--interregnum .room-name { font-size: 28px; }

/* ---------- Bays (a work and its label) ---------- */

.bay {
  flex: none;
  margin: 0;
  display: flex; align-items: center; gap: 48px;
}
/* A pendant pair hangs side by side, labels on the outer edges. */
.bay--pair-start { flex-direction: row-reverse; margin-right: calc(56px - var(--bay-gap)); }

.hang { position: relative; }
/* Gallery lighting: a soft pool of light on the wall behind each work. */
.hang::before {
  content: "";
  position: absolute; inset: -22% -38%;
  background: radial-gradient(ellipse at 50% 42%, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 62%);
  pointer-events: none;
}
.hang img {
  position: relative;
  height: var(--hang-h);
  width: auto;
  max-width: 62vw;
  object-fit: contain;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.18),
    0 22px 44px -20px rgba(0, 0, 0, 0.45);
}

.label {
  width: var(--label-w);
  font-size: 14px;
}
.label-no { font-size: 22px; font-weight: 700; }
.label-title {
  margin-top: 8px;
  font-size: 21px; line-height: 1.2; font-weight: 400; font-style: italic;
}
.label-title em { font-style: normal; }
.label-meta { margin-top: 10px; }
.label-medium { color: var(--ink-soft); }
.label-text { margin-top: 14px; color: var(--ink-soft); }
.label .listen { margin-top: 18px; }

/* ---------- Audio guide ---------- */

.listen {
  display: inline-flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 13px; font-weight: 600; letter-spacing: 0.04em;
}
.listen-icon, .now-playing-icon {
  position: relative; flex: none;
  width: 30px; height: 30px;
  border: 1.5px solid var(--ink); border-radius: 50%;
}
/* Play triangle */
.listen-icon::after, .now-playing-icon::after {
  content: "";
  position: absolute; left: 11px; top: 8.5px;
  border-style: solid; border-width: 5.5px 0 5.5px 9px;
  border-color: transparent transparent transparent var(--ink);
}
.listen:hover .listen-icon { background: rgba(0, 0, 0, 0.06); }
/* Pause bars while playing */
.listen.is-playing .listen-icon, .now-playing-icon { background: var(--ink); }
.listen.is-playing .listen-icon::after, .now-playing-icon::after {
  left: 9.5px; top: 9px;
  width: 8px; height: 9px;
  border: 0;
  border-left: 3px solid var(--paper); border-right: 3px solid var(--paper);
}

/* ---------- Exit ---------- */

.exit {
  width: max(78vw, 720px);
  background: var(--paper);
  /* Generous right margin: this is the end of the wall, so it shouldn't feel cut off. */
  padding: 0 clamp(120px, 16vw, 280px) 0 clamp(80px, 9vw, 160px);
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
}
.exit-title { font-size: clamp(56px, 10vh, 104px); font-weight: 900; font-stretch: 62%; text-transform: uppercase; line-height: 0.88; }
.exit-text { margin-top: 24px; max-width: 42ch; font-size: 16px; color: var(--ink-soft); }
.exit-links { margin-top: 32px; display: flex; flex-wrap: wrap; gap: 12px; }

/* ---------- Floor ---------- */

.floor {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--floor-h);
  background-color: var(--floor);
  /* Contact shadow at the skirting, a soft sheen of reflected wall light falling off toward the
     viewer, then polished concrete.
     Every layer repeats so the floor drift in walk.js can shift them all. */
  background-image:
    linear-gradient(to bottom, rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0) 22px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.20), rgba(255, 255, 255, 0.06) 40%, rgba(255, 255, 255, 0) 70%, rgba(0, 0, 0, 0.06)),
    url("floor.webp");
  /* The tile is squashed vertically so the floor reads as receding, not seen from above. */
  background-size: 100% 100%, 100% 100%, 1152px 512px;
  /* A slim shadow gap at the base of the wall, in place of a painted skirting. */
  box-shadow: inset 0 2px 0 var(--floor-edge), inset 0 3px 0 rgba(0, 0, 0, 0.10);
}

/* ---------- HUD: floor plan and whereabouts ---------- */

/* Anchored to the bottom of the floor so it sits clear of the wall. */
.hud {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  height: var(--floor-h);
  padding: 0 var(--gutter) 22px;
  display: flex; flex-direction: column; justify-content: flex-end;
  pointer-events: none;
}
.hud > * { pointer-events: auto; }

.plan {
  position: relative;
  display: flex; height: 10px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}
.plan button {
  height: 100%; border: 0; padding: 0; cursor: pointer;
  background: var(--seg);
  box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.12);
}
.plan button:hover { filter: brightness(0.94); }
.plan-marker {
  position: absolute; top: -6px; bottom: -6px; width: 2px;
  background: var(--ink);
  pointer-events: none;
  left: 0;
}

/* Wayfinding sign for a floor plan segment (positioned by walk.js). */
.plan-tip {
  position: absolute; left: 0; top: 0;
  transform: translateX(-50%) translateY(4px);
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 14px 10px;
  background: var(--ink); color: var(--paper);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease, transform 120ms ease;
}
.plan-tip.is-visible { opacity: 1; transform: translateX(-50%); }
.plan-tip-kicker { font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; }
.plan-tip-name { font-size: 16px; font-weight: 700; font-stretch: 75%; }
.plan-tip-dates { font-size: 12px; opacity: 0.75; }

/* Always as tall as the now-playing control, so the floor plan doesn't jump when audio starts. */
.hud-row {
  margin-top: 14px;
  min-height: 26px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-size: 13px;
}
.whereabouts, .now-playing { white-space: nowrap; }
.whereabouts { font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; }

.now-playing {
  display: inline-flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 13px; font-weight: 600;
}
.now-playing[hidden] { display: none; }
.now-playing-icon { width: 26px; height: 26px; }
.now-playing-icon::after { left: 7.5px; top: 7px; }

/* ---------- Index: the gallery guide (paper, folds and signs from guide.css) ---------- */

.index {
  --panel-pad: 40px 48px;
  width: min(936px, calc(100vw - 32px));
  max-height: calc(100dvh - 48px);
  border: 0; padding: 0;
  overflow: auto;
  font-family: var(--font);
}
.index::backdrop { background: rgba(17, 17, 17, 0.5); }
.index-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; margin-top: 28px !important; }
.index-title {
  font-size: clamp(40px, 6vw, 64px); line-height: 0.9;
  font-weight: 900; font-stretch: 62%; text-transform: uppercase;
}
.index-close {
  flex: none;
  background: none; border: 1px solid currentColor; padding: 8px 14px; cursor: pointer;
  font-size: 14px; font-weight: 600;
}
.index-close:hover { background: var(--ink); color: var(--paper); }
.index-intro { max-width: 560px; color: var(--ink-soft); }
.index-dates { margin-top: 10px !important; font-size: 14px; color: var(--ink-soft); }
.index-empty { max-width: 560px; font-size: 15px; color: var(--ink-soft); }

.index-works {
  list-style: none; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px 28px;
}
.index-works button {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px; align-items: start;
  width: 100%; background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
}
.index-works img {
  width: 64px; height: 80px; object-fit: cover;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 6px 12px -6px rgba(0, 0, 0, 0.4);
}
.index-no { display: block; font-size: 18px; font-weight: 800; font-stretch: 75%; color: var(--spot, var(--ink)); }
.index-work-title { display: block; font-size: 15px; font-style: italic; line-height: 1.3; }
.index-work-title em { font-style: normal; }
.index-date { display: block; margin-top: 4px; font-size: 13px; color: var(--ink-soft); }
.index-works button:hover .index-work-title { text-decoration: underline; text-underline-offset: 3px; }
.index-foot p { font-size: 15px; color: var(--ink-soft); }
.index-foot a { color: var(--ink); font-weight: 600; }

/* ---------- Phones ---------- */

@media (max-width: 760px) {
  :root {
    --gutter: 16px;
    --topbar-h: 52px;
    --floor-h: 72px;
    --hang-h: min(40vh, 420px);
    --bay-gap: 8vw;
  }

  .topnav { gap: 20px; font-size: 13px; }


  .entrance { width: 100vw; overflow-y: auto; padding-bottom: 20px; }
  .entrance-title { font-size: clamp(64px, 24vw, 120px); }
  .entrance-tagline { font-size: 16px; margin-top: 18px; }
  .entrance-block { --facts-gap: 24px; }
  .entrance-intro { font-size: 14px; }
  .entrance-facts { gap: 32px; }
  .entrance-facts dd { font-size: 16px; }
  .entrance-main { margin-top: 18px; }

  /* Stacked works hang from one shared top line, so images and labels line up as you walk. */
  .room {
    padding: calc(var(--topbar-h) + 20px) var(--bay-gap) 0 7vw;
    align-items: flex-start;
  }
  .room-intro { padding-top: 0; align-self: flex-start; }
  .room--interregnum { align-items: center; padding-top: 0; }
  .room--interregnum .room-intro { align-self: center; }
  .room-intro { width: 76vw; }
  .room-name { font-size: 36px; }
  .room--interregnum { width: 90vw; }

  .bay {
    flex-direction: column; align-items: flex-start; gap: 16px;
    max-height: calc(var(--wall-h) - var(--topbar-h) - 28px);
  }
  /* Every image gets the same frame height, top-aligned, so labels start on one line too. */
  .hang { flex: none; height: var(--hang-h); display: flex; align-items: flex-start; }
  .bay .label { min-height: 0; }
  .bay--pair-start { flex-direction: column; margin-right: 0; }
  .hang img { max-width: 74vw; height: auto; max-height: var(--hang-h); }
  .label {
    width: min(74vw, 360px); overflow-y: auto; font-size: 13px;
    display: flex; flex-direction: column;
  }
  /* Keep the audio guide in reach above the placard text. */
  .label .listen { order: 1; margin-top: 12px; align-self: flex-start; }
  .label-text { order: 2; }
  .label-no { font-size: 18px; }
  .label-title { font-size: 18px; margin-top: 4px; }

  .exit { width: 100vw; padding: 0 var(--gutter); }

  .index { --panel-pad: 28px 20px; width: calc(100vw - 16px); max-height: calc(100dvh - 16px); }
  .index-head { flex-wrap: wrap; }

  .hud { padding-bottom: 12px; }
  .hud-row { margin-top: 10px; font-size: 12px; }
}

/* ---------- Touch ---------- */

/* Swipes settle on a stop. Only for touch: with a mouse or trackpad, snapping fights the
   wheel glide, whatever the window width. */
@media (pointer: coarse) {
  .walk { scroll-snap-type: x proximity; }
  .stop, .room-intro, .bay { scroll-snap-align: center; }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  body.at-entrance .enter .button-arrow { animation: none; }
  *, *::before, *::after { transition: none !important; scroll-behavior: auto !important; }
}
