/* ==========================================================================
   Chitrakutah
   --------------------------------------------------------------------------
   The paintings are the only saturated colour on this site. The interface is
   warm near-neutral throughout and has NO accent hue, deliberately: any
   accent worth the name would compete with her skies. Interaction is carried
   by ink weight, underline and focus ring instead.

   The page is committed to a light paper ground. There is no dark mode by
   choice — a painting seen on black is a different painting.
   ========================================================================== */

:root {
  /* --- Ground and ink ---------------------------------------------------- */
  --paper:      #f4f2ed;  /* warm rag-paper white */
  --paper-sunk: #ebe8e1;  /* recessed areas, inputs */
  --ink:        #25221e;  /* 14.3:1 on paper */
  --ink-soft:   #57524b;  /*  6.2:1 — secondary prose */
  --ink-faint:  #5f594f;  /*  6.2:1 on paper, 5.2:1 over the background art */
  --rule:       #dcd7cd;  /* decorative dividers only — exempt from 1.4.11 */

  /* One of Lekha's paintings sits behind the whole site. Swap the file to
     change it; --bg-strength is the only dial you need. Raising it much past
     0.2 starts eating the contrast the small text depends on — see below. */
  --bg-art: url("../images/open-water-grey-day.jpg");
  --bg-strength: 0.18;

  /* The edge of a control is what tells you it is a control, so it has to meet
     the 3:1 non-text contrast rule. --rule is far too faint for that (1.28:1);
     this is 3.6:1 against the paper. Inputs and chips use it, dividers do not. */
  --control-edge: #7a7366;

  /* The lightbox stage: warm dark, not black, so the white paper edges of
     the watercolours still read as paper. */
  --stage:       #1a1917;
  --stage-ink:   #edeae4;
  --stage-faint: #a8a29a;
  --stage-rule:  #3a3833;

  /* --- Type ------------------------------------------------------------- */
  /* Iowan Old Style and Hoefler Text ship with macOS/iOS; Charter is widely
     present on Linux. Self-hosted, i.e. nothing is fetched from a CDN. */
  --serif: "Iowan Old Style", "Hoefler Text", Charter, "Palatino Linotype",
           Palatino, "Book Antiqua", Georgia, serif;
  --sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, sans-serif;

  /* Fluid type scale, 360px → 1400px viewport. */
  --t-wordmark: clamp(1.0625rem, 0.98rem + 0.35vw, 1.25rem);
  --t-display:  clamp(1.875rem, 1.35rem + 2.6vw, 3.5rem);
  --t-title:    clamp(1.375rem, 1.15rem + 1.0vw, 1.875rem);
  --t-body:     clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --t-small:    0.875rem;
  --t-label:    0.6875rem;

  /* --- Space ------------------------------------------------------------ */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4.5rem;
  --s-9: 7rem;

  --measure: 34rem;                  /* prose column */
  --gutter: clamp(1.25rem, 4vw, 4rem);
  /* Never narrower than the old fixed 78rem, which laptops were laid out
     against; grows with the screen past that, to 90% of the width and at most
     150rem. The fixed version left a 27-inch monitor 56% empty. This is a
     max-width, so on a phone it simply fills the screen. */
  --page: max(78rem, min(90vw, 150rem));

  --focus: #25221e;
}

/* --- Reset (minimal) ---------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  /* Type, spacing and the prose measure are all in rem, so nudging the root
     size up on big monitors scales the whole interface together. Text that
     reads comfortably on a laptop is too small at arm's length on a 27-inch
     screen; the paintings scale separately, in js/gallery.js. */
  font-size: 100%;
}
@media (min-width: 1800px) { html { font-size: 106.25%; } }  /* 17px */
@media (min-width: 2300px) { html { font-size: 112.5%;  } }  /* 18px */
@media (min-width: 3200px) { html { font-size: 125%;    } }  /* 20px */

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--t-body);
  line-height: 1.6;
  /* Not synthesising bold/italic on the serif stack keeps it honest. */
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }

/* The background painting. position:fixed keeps it out of the body's flex flow
   and avoids the jank that background-attachment:fixed causes on phones. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image: var(--bg-art);
  background-size: cover;
  background-position: center;
  opacity: var(--bg-strength);
  pointer-events: none;
}

h1, h2, h3 { font-weight: 400; margin: 0; line-height: 1.18; }

p { margin: 0 0 var(--s-4); }

ul { margin: 0; padding: 0; list-style: none; }

/* --- Links -------------------------------------------------------------- */

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--rule);
  transition: text-decoration-color 160ms ease;
}
a:hover { text-decoration-color: var(--ink); }

/* Visible focus everywhere. Never removed, only replaced. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 1px;
}
.stage :focus-visible { outline-color: var(--stage-ink); }

/* --- Utility ------------------------------------------------------------ */

.wrap {
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.measure { max-width: var(--measure); }

/* Small email and Instagram marks beside their links. Drawn in the text colour,
   so they follow whatever ink the link is set in. */
.icon {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}
a.icon-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
}

/* Email and Instagram at the foot of the About text. */
.contact-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-6);
  margin-top: var(--s-5);
}
.contact-links a { padding-block: 0.625rem; margin-block: -0.625rem; }

/* Reading pages. The gallery should use a big screen's width; a page of text
   and a form should not — spread across 90% of a 27-inch monitor they fall apart
   into a column at each edge with a gulf between. These sit in one centred
   column instead, with the heading aligned to it. */
.page-head.wrap,
.about-grid.wrap,
.contact-grid.wrap { max-width: min(var(--page), 72rem); }

.label {
  font-family: var(--sans);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: var(--s-4); top: var(--s-4);
  z-index: 100;
  padding: var(--s-2) var(--s-4);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--t-small);
  transform: translateY(-160%);
}
.skip:focus { transform: none; }

/* ==========================================================================
   Masthead
   ========================================================================== */

.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3) var(--s-5);
  padding-block: var(--s-5) var(--s-6);
}

.wordmark {
  font-family: var(--serif);
  font-size: var(--t-wordmark);
  /* The name means, roughly, "the many-coloured peak". Letterspacing it
     wide is the whole of the identity — no motif, no ornament. */
  letter-spacing: 0.26em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
.wordmark:hover { text-decoration: none; }

.nav ul {
  display: flex;
  gap: var(--s-5);
  font-family: var(--sans);
  font-size: var(--t-small);
}

.nav a {
  text-decoration: none;
  /* 44px tall to tap, without changing how the row looks. */
  display: inline-block;
  padding-block: 0.8125rem;
  margin-block: -0.8125rem;
}
.nav a:hover { text-decoration: underline; }

/* Current page is stated, not coloured. */
.nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--ink);
}

/* ==========================================================================
   Opening statement (home)
   ========================================================================== */

.opening { padding-block: var(--s-7) var(--s-8); }

.opening h1 {
  font-size: var(--t-display);
  letter-spacing: -0.015em;
  max-width: 26ch;
  margin-bottom: var(--s-5);
}

.opening .standfirst {
  max-width: var(--measure);
  color: var(--ink-soft);
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  line-height: 1.65;
  margin-bottom: 0;
}

/* ==========================================================================
   The hang
   --------------------------------------------------------------------------
   Works are sized to roughly equal visual AREA and share one horizontal
   centre axis per row, which is how paintings are really hung in a room.
   A tall canvas therefore reads tall and a wide one reads wide. Widths and
   heights come from js/gallery.js as --w / --h in pixels; the aspect-ratio
   fallback below keeps the box correct if those are ever missing.
   ========================================================================== */

.hang {
  display: flex;
  flex-wrap: wrap;
  align-items: center;              /* <- the hanging line */
  justify-content: center;
  gap: var(--s-8) var(--s-7);
  padding-bottom: var(--s-8);
}

.work { margin: 0; }

.work-btn {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.work-frame {
  width: var(--w, 20rem);
  max-width: 100%;
}

.work-frame img {
  width: 100%;
  height: auto;
  aspect-ratio: var(--ar, 1);
  object-fit: contain;               /* never crop a painting */
  /* A painting hangs on a wall; it does not float in a void. The shadow is
     the only effect on this site and it is nearly invisible on purpose. */
  box-shadow: 0 1px 2px rgba(37, 34, 30, 0.07),
              0 8px 24px -12px rgba(37, 34, 30, 0.18);
  transition: box-shadow 220ms ease, transform 220ms ease;
}

/* The lift is a hover affordance. On a phone a tap leaves :hover stuck on the
   painting until the next tap elsewhere, so only offer it to real pointers.
   Keyboard focus keeps it everywhere. */
@media (hover: hover) and (pointer: fine) {
  .work-btn:hover .work-frame img {
    box-shadow: 0 1px 2px rgba(37, 34, 30, 0.09),
                0 14px 34px -14px rgba(37, 34, 30, 0.26);
    transform: translateY(-2px);
  }
}
.work-btn:focus-visible .work-frame img {
  box-shadow: 0 1px 2px rgba(37, 34, 30, 0.09),
              0 14px 34px -14px rgba(37, 34, 30, 0.26);
  transform: translateY(-2px);
}

/* Caption sits under the work, quiet and consistent. */
.work-caption {
  margin-top: var(--s-3);
  max-width: 26rem;
}

.work-caption .t {
  display: block;
  font-size: var(--t-body);
  line-height: 1.35;
}

.work-caption .m {
  display: block;
  margin-top: 0.2em;
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-faint);
  line-height: 1.45;
}

/* --- Section heads ------------------------------------------------------ */

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3) var(--s-5);
  padding-bottom: var(--s-6);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s-7);
}

.section-head h2 { font-size: var(--t-title); }

.section-head .more { font-family: var(--sans); font-size: var(--t-small); }

/* --- Filters (built, dormant until there are more paintings) ------------ */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  padding-bottom: var(--s-7);
}
.filters[hidden] { display: none; }

.chip {
  font-family: var(--sans);
  font-size: var(--t-small);
  padding: var(--s-2) var(--s-4);
  background: none;
  border: 1px solid var(--control-edge);
  border-radius: 999px;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease;
}
.chip:hover { border-color: var(--ink-faint); color: var(--ink); }
.chip[aria-pressed="true"] {
  border-color: var(--ink);
  color: var(--ink);
}

/* ==========================================================================
   Prose pages (About, Contact)
   ========================================================================== */

.page-head { padding-block: var(--s-7) var(--s-6); }
.page-head h1 { font-size: var(--t-display); letter-spacing: -0.015em; }

.prose { max-width: var(--measure); padding-bottom: 0; }
.prose > :last-child { margin-bottom: 0; }
.prose p { color: var(--ink-soft); }
.prose p.lead { color: var(--ink); font-size: 1.125rem; }
.prose h2 {
  font-size: var(--t-title);
  margin-top: var(--s-7);
  margin-bottom: var(--s-4);
}

/* ...except the first one, which would otherwise open with a large gap under
   the page heading. */
.prose > h2:first-child { margin-top: 0; }


/* About: portrait beside the text, stacked on narrow screens. */
.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
  padding-bottom: var(--s-6);
  align-items: start;
}

@media (min-width: 56rem) {
  .about-grid {
    grid-template-columns: minmax(0, 22rem) minmax(0, var(--measure));
    gap: var(--s-8);
  }
}

.portrait figure { margin: 0; }
.portrait img {
  box-shadow: 0 1px 2px rgba(37, 34, 30, 0.07),
              0 8px 24px -12px rgba(37, 34, 30, 0.18);
}
.portrait figcaption {
  margin-top: var(--s-3);
  font-family: var(--serif);
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink-soft);
}

/* ==========================================================================
   Contact
   ========================================================================== */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
  padding-bottom: var(--s-6);
  align-items: start;
}

@media (min-width: 56rem) {
  .contact-grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--s-8);
  }
}

/* The form sits on its own sheet of paper, so it stays legible over whichever
   painting is behind the site and reads as something to fill in. */
.form-panel {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: clamp(1.25rem, 3vw, 2.25rem);
  box-shadow: 0 1px 2px rgba(37, 34, 30, 0.05),
              0 18px 40px -28px rgba(37, 34, 30, 0.35);
}

.contact-aside { display: grid; gap: var(--s-6); }

.contact-art figure, .contact-art { margin: 0; }

.contact-art img {
  border-radius: 2px;
  box-shadow: 0 1px 2px rgba(37, 34, 30, 0.07),
              0 12px 30px -16px rgba(37, 34, 30, 0.3);
}

.contact-art figcaption {
  margin-top: var(--s-3);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-faint);
}

.field { margin-bottom: var(--s-5); }

.field label {
  display: block;
  font-family: var(--sans);
  font-size: var(--t-small);
  margin-bottom: var(--s-2);
}

.field .hint {
  display: block;
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-faint);
  margin-bottom: var(--s-2);
}

.field input,
.field textarea {
  width: 100%;
  font-family: var(--serif);
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--paper-sunk);
  border: 1px solid var(--control-edge);
  border-radius: 2px;
  padding: var(--s-3);
  transition: border-color 160ms ease;
}

.field input:hover,
.field textarea:hover { border-color: var(--ink-faint); }

.field input:focus,
.field textarea:focus { border-color: var(--ink); }

.field textarea { min-height: 9rem; resize: vertical; }

/* Errors are specific and unapologetic — see js/gallery.js for the copy. */
.field.is-invalid input,
.field.is-invalid textarea { border-color: #8c2f22; }

.field-error {
  display: none;
  font-family: var(--sans);
  font-size: var(--t-small);
  color: #8c2f22;                    /* 5.6:1 on paper */
  margin-top: var(--s-2);
}
.field.is-invalid .field-error { display: block; }

button.submit {
  min-height: 48px;
  font-family: var(--sans);
  font-size: var(--t-small);
  letter-spacing: 0.06em;
  padding: var(--s-3) var(--s-6);
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 2px;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease;
}
button.submit:hover { background: none; color: var(--ink); }
button.submit[disabled] { opacity: 0.5; cursor: default; }

/* The "open in my email app" hand-off, styled as the primary action. */
a.submit-link {
  display: inline-block;
  font-family: var(--sans);
  font-size: var(--t-small);
  letter-spacing: 0.06em;
  padding: var(--s-3) var(--s-6);
  margin-top: var(--s-2);
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 2px;
  text-decoration: none;
  transition: background-color 160ms ease, color 160ms ease;
}
a.submit-link:hover { background: none; color: var(--ink); text-decoration: none; }

.form-success .alt-route {
  margin-top: var(--s-4);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-faint);
}

/* Honeypot: hidden from people, present for bots. */
.hp { position: absolute; left: -9999px; opacity: 0; }

.form-status { margin-top: var(--s-5); }

.form-success {
  border-top: 1px solid var(--ink);
  padding-top: var(--s-5);
}
.form-success h2 { font-size: var(--t-title); margin-bottom: var(--s-3); }

.direct dt {
  font-family: var(--sans);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--s-1);
}
.direct dd { margin: 0 0 var(--s-5); }

/* ==========================================================================
   Lightbox
   ========================================================================== */

.stage {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  /* minmax(0, 1fr), not 1fr: a bare 1fr is minmax(auto, 1fr), whose auto
     minimum lets the row grow to the image's natural height. A tall canvas then
     overflows the stage — and since the stage is fixed with page scrolling
     locked, the overflow is unreachable. */
  grid-template-rows: minmax(0, 1fr) auto;
  background: var(--stage);
  color: var(--stage-ink);
  padding: var(--gutter);
  gap: var(--s-5);
}
.stage[hidden] { display: none; }

.stage-figure {
  margin: 0;
  min-height: 0;
  display: grid;
  place-items: center;
}

.stage-figure img {
  /* max-width resolves fine (the column width is definite) but max-height:100%
     does NOT: a grid area's height counts as indefinite for percentage
     resolution, so it silently computes to `none` and a tall canvas overflows
     the stage. js/gallery.js sets both caps in pixels from the measured figure
     instead. Keeping the image at its own intrinsic ratio — rather than
     stretching it to the box and relying on object-fit — is what lets the
     shadow hug the canvas edge and keeps the 10cm scale rule honest. */
  max-width: 100%;
  width: auto; height: auto;
  object-fit: contain;
  box-shadow: 0 24px 60px -24px rgba(0, 0, 0, 0.7);
}

.stage-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--s-4) var(--s-6);
  border-top: 1px solid var(--stage-rule);
  padding-top: var(--s-4);
}

.stage-meta h2 { font-size: var(--t-title); }

.stage-meta .m,
.stage-meta .note {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--stage-faint);
  margin: var(--s-2) 0 0;
  max-width: 42rem;
}
.stage-meta .note { font-family: var(--serif); font-size: var(--t-body); }

.stage-actions { display: flex; gap: var(--s-2); flex-shrink: 0; }

.stage-btn {
  font-family: var(--sans);
  font-size: var(--t-small);
  min-height: 44px;
  min-width: 44px;
  padding: var(--s-2) var(--s-4);
  background: none;
  color: var(--stage-ink);
  border: 1px solid var(--stage-rule);
  border-radius: 2px;
  cursor: pointer;
  transition: border-color 160ms ease;
}
.stage-btn:hover { border-color: var(--stage-faint); }
.stage-btn[aria-pressed="true"] { border-color: var(--stage-ink); }
.stage-count {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--stage-faint);
  align-self: center;
  padding-inline: var(--s-2);
  font-variant-numeric: tabular-nums;
}

/* A photograph of a canvas loses its size. When real dimensions exist in the
   JSON, this draws a true 10cm rule against the displayed image. */
.scalebar {
  margin-top: var(--s-3);
  font-family: var(--sans);
  font-size: var(--t-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--stage-faint);
}
.scalebar[hidden] { display: none; }
.scalebar .rule {
  display: block;
  height: 5px;
  width: var(--scale-w, 3rem);
  border: 1px solid var(--stage-faint);
  border-top: 0;
  margin-bottom: 0.3em;
}

/* ==========================================================================
   Notices — malformed JSON, empty data, no-JS
   ========================================================================== */

.notice {
  max-width: var(--measure);
  border-top: 2px solid var(--ink);
  padding-top: var(--s-4);
  margin-bottom: var(--s-8);
}
.notice h2 { font-size: var(--t-title); margin-bottom: var(--s-3); }
.notice p { color: var(--ink-soft); }
.notice code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.875em;
  background: var(--paper-sunk);
  padding: 0.1em 0.35em;
  border-radius: 2px;
}
.notice .detail {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--t-small);
  color: var(--ink-faint);
  white-space: pre-wrap;
  word-break: break-word;
}

/* Reserve vertical space while the JSON is in flight so the footer does not
   jump up and then back down. */
.hang-loading { min-height: 60vh; }

.notice-min {
  max-width: var(--measure);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-soft);
}

/* Failure notices sit on paper so they stay readable over the background art. */
.notice {
  background: var(--paper);
  padding: var(--s-5);
  border-radius: 3px;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  border-top: 1px solid var(--rule);
  padding-block: var(--s-5) var(--s-6);
  margin-top: var(--s-6);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4) var(--s-6);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-faint);
}

.footer-inner ul { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }
.footer-inner a {
  display: inline-flex;
  align-items: center;
  padding-block: 0.8125rem;
  margin-block: -0.8125rem;
}

body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100svh; }
main { flex: 0 0 auto; }

/* These are flex items of <body>. `.wrap` gives them `margin-inline: auto`,
   and an auto margin on the cross axis cancels `align-items: stretch` — so
   without this they collapse to the width of their own content. */
body > header,
body > main,
body > footer { width: 100%; }

/* ==========================================================================
   Narrow screens — the gallery is tested at 360px specifically
   ========================================================================== */

@media (max-width: 40rem) {
  .hang {
    gap: var(--s-7) var(--s-5);
  }
  /* One work per row: proportions stay true, nothing is ever squeezed. */
  .work { width: 100%; }
  .work-frame { width: 100%; max-width: var(--w, 100%); margin-inline: auto; }

  .stage {
    grid-template-rows: minmax(0, 1fr) auto;
    padding: var(--s-4);
    gap: var(--s-4);
  }
  .stage-meta { align-items: start; }
  .stage-actions { width: 100%; justify-content: space-between; }
  .stage-count { flex: 1; text-align: center; }

  /* Thumb-sized send button, full width. */
  button.submit { width: 100%; }

  .page-head { padding-block: var(--s-6) var(--s-5); }
  .opening { padding-block: var(--s-5) var(--s-7); }
  .nav ul { gap: var(--s-4); }
  .wordmark { letter-spacing: 0.18em; }
}

@media (min-width: 40.01rem) and (max-width: 64rem) {
  .hang { gap: var(--s-7) var(--s-6); }
}

/* On very large screens give the paintings more air between them, in step with
   their larger size. */
@media (min-width: 1800px) {
  .hang { gap: var(--s-9) var(--s-8); }
}

/* ==========================================================================
   Motion and print
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .work-btn:hover .work-frame img,
  .work-btn:focus-visible .work-frame img { transform: none; }
}

@media print {
  .nav, .filters, .stage, .skip { display: none; }
  body { background: #fff; }
  .work-frame img { box-shadow: none; }
}
