/* =====================================================================
   CAN TATTOO: shared styles for Home, Artists & Flash and Enquiries
   ---------------------------------------------------------------------
   How this file is organised
     1. Tokens (colours, type, spacing, motion)   <- change the look here
     2. Base + print texture
     3. Layout helpers
     4. Header + navigation
     5. Buttons + links
     6. Artwork frames (completed tattoo vs flash design)
     7. Home sections
     8. Artists & Flash sections (8b: the Enquiries page)
     9. Enquiry panel + footer
    10. Image viewer (lightbox)
    11. Motion (only active when html has the .motion class)
    12. Reduced motion + no-motion safety
   ===================================================================== */

/* 1. TOKENS ----------------------------------------------------------- */
/* --jump-h is registered as a length so it resolves to px (a script or test
   reading it gets a pixel length, not the max() expression) */
@property --jump-h { syntax: "<length>"; inherits: true; initial-value: 44px; }
:root {
  /* Palette. Red is the dominant brand colour; yellow is a sparing accent. */
  --red: #901c12;          /* the logo's red (from the supplied artwork): every red on the site */
  --red-deep: #73160e;     /* a darker step of the logo red, only for the red button's hover and press */
  --ink: #1b1715;          /* text and structure */
  --ink-soft: #3b332e;     /* secondary text on paper (9.8:1 on --paper) */
  --paper: #f0e4ce;        /* page surface */
  --paper-deep: #e6d6ba;   /* recessed paper bands */
  --paper-light: #f7efdf;  /* flash sheets, mats */
  --yellow: #f0c15e;       /* the logo's marigold: header logo label, trim on red panels, accents on ink */

  /* Type */
  --font-display: "Anybody", "Impact", "Haettenschweiler", "Arial Narrow Bold", sans-serif;
  --font-text: "Instrument Sans", "Instrument Sans Fallback", Arial, Helvetica, sans-serif;

  --step--1: clamp(0.84rem, 0.8rem + 0.15vw, 0.9rem);
  --step-0: clamp(1.02rem, 0.97rem + 0.25vw, 1.15rem);
  --step-1: clamp(1.2rem, 1.08rem + 0.55vw, 1.5rem);
  --step-2: clamp(1.55rem, 1.3rem + 1.1vw, 2.2rem);
  --step-3: clamp(2.1rem, 1.6rem + 2.4vw, 3.6rem);
  --step-4: clamp(2.8rem, 1.9rem + 4.4vw, 5.8rem);

  /* Space */
  --gutter: clamp(16px, 4vw, 56px);
  --section: clamp(72px, 9vw, 152px);
  --maxw: 1480px;
  --header-h: 60px;       /* height of the sticky header band (56px on phones) */
  --jump-h: max(44px, 2.75rem); /* desktop artist row; the phone wheel overrides this in section 8 */

  /* Motion */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-print: cubic-bezier(0.65, 0, 0.35, 1);

  /* Focus ring colour switches per surface (see .on-red, .on-ink) */
  --focus: var(--ink);
  --focus-halo: var(--paper);

  /* Print grain textures (used as backgrounds only, never over artwork) */
  --grain-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .1 0 0 0 0 .08 0 0 0 0 .06 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.26'/%3E%3C/svg%3E");
  --grain-red: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .06 0 0 0 0 .02 0 0 0 0 .02 0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.3'/%3E%3C/svg%3E");

  color-scheme: light;
}

/* 2. BASE ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 16px);
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--paper);
  /* Subtle print grain. It sits on the page background, never over artwork. */
  background-image: var(--grain-paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--step-0);
  line-height: 1.6;
  font-optical-sizing: auto;
  overflow-x: clip;
}

html { overflow-x: clip; }
@supports not (overflow: clip) {
  /* html only: it propagates to the viewport, so sticky keeps working */
  html { overflow-x: hidden; }
}
[hidden] { display: none !important; }

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

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-variation-settings: "wdth" 72;
  line-height: 0.98;
  letter-spacing: 0.005em;
  text-wrap: balance;
}

p { margin: 0 0 1em; max-width: 62ch; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

/* Enlarged text: a word too long for its column (big lettering, the handle in
   the enquiry panel, a caption under a small frame) breaks onto the next line
   instead of running off the screen. Only a word that can't fit breaks, so
   text at normal size is unchanged. */
h1, h2, h3, .caption, .enquiry__handle { overflow-wrap: anywhere; }

/* Visible keyboard focus everywhere */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--focus-halo);
}
.on-red { --focus: var(--paper); --focus-halo: var(--ink); }
.on-ink { --focus: var(--yellow); --focus-halo: var(--ink); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* Studio logo: one traced symbol (#can-logo) in each page, drawn in
   currentColor so it can sit on red, paper or ink. Sized by height or width
   at each use; the aspect ratio keeps it true to the supplied artwork. */
.logo-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.logo { display: block; fill: currentColor; aspect-ratio: 846 / 89.8; }

.skip-link {
  position: absolute;
  left: 12px; top: -80px;
  z-index: 100;
  padding: 12px 16px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-weight: 700;
  text-decoration: none;
}
.skip-link:focus { top: 12px; --focus: var(--yellow); }

/* Placeholder / to-be-confirmed marker used in copy */
.tbc {
  display: inline-block;
  padding: 0 0.35em;
  border: 1px dashed currentColor;
  font-family: var(--font-display);
  font-size: 0.78em;
  font-weight: 600;
  font-variation-settings: "wdth" 90;
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: 0.08em;
}

/* 3. LAYOUT HELPERS --------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section); }

/* 4. HEADER + NAVIGATION ---------------------------------------------- */
/* A red band (the logo red), like the cover strip of a printed catalogue. The page
   you are on is a paper tab that joins the page below it.
   Phones (with JavaScript): one slim sticky row; Menu opens the original red sheet.
   Phones without JavaScript: logo + enquiry link, then the three page tabs
   (the row wraps when text is enlarged). */
.site-header {
  position: relative;
  z-index: 40;
  background-color: var(--red);
  background-image: var(--grain-red);
  color: var(--paper);
  box-shadow: inset 0 -2px 0 var(--ink); /* ink rule; the current tab covers it */
}
.site-header__inner {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "mark cta" "nav nav";
  align-items: center;
  column-gap: 12px;
}
.wordmark {
  grid-area: mark;
  justify-self: start;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  min-height: 52px;
  padding-inline: 10px;
  margin-inline: -10px;
  color: var(--red);
  text-decoration: none;
}
/* The logo sits on its own flat yellow label, as in the supplied artwork.
   The padding and matching negative margin let the label hang 10px into the
   gutter while the letters line up with the page; the whole label is the
   link. The focus ring is drawn round the label itself, evenly spaced and
   inside the band, so the 56px phone header never clips it. */
.wordmark::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 8px 0;
  background-color: var(--yellow);
}
.wordmark:focus-visible { outline: none; box-shadow: none; }
.wordmark:focus-visible::before { outline: 3px solid var(--focus); outline-offset: 2px; }
.wordmark .logo { height: clamp(15px, 12.5px + 0.45vw, 19px); }
.site-nav { grid-area: nav; }
.site-nav ul {
  display: flex;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-nav a,
.header-cta,
.menu-toggle {
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 750;
  font-variation-settings: "wdth" 100;
  letter-spacing: 0.08em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
.site-nav a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 16px;
  color: var(--paper);
}
.site-nav li:first-child a:not([aria-current]) { padding-left: 0; }
.site-nav a[aria-current="page"] {
  background-color: var(--paper);
  background-image: var(--grain-paper);
  color: var(--red);
}
.header-cta {
  grid-area: cta;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 16px;
  border: 2px solid var(--paper);
  color: var(--paper);
  transition: background-color 160ms ease, color 160ms ease, transform 140ms var(--ease-out);
}
.header-cta:active { transform: scale(0.97); }
@media (hover: hover) and (pointer: fine) {
  .header-cta:hover { background: var(--paper); color: var(--red); }
  .site-nav a:not([aria-current]):hover { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.45em; }
}
/* Phones without JavaScript: the header wraps rather than running off the
   screen when text is enlarged. The logo label and enquiry link share the top
   row while they fit; otherwise the enquiry link drops to a row of its own.
   The page tabs always stay together on the bottom row, stretched to the same
   height, so the current tab still joins the page; a tab name breaks onto a
   second line instead of running off the screen. At normal text size nothing
   wraps (see the small-phone rules below). */
@media (max-width: 719px) {
  html:not(.js) .site-header__inner {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  html:not(.js) .site-nav { order: 1; flex-basis: 100%; }
  html:not(.js) .site-nav li { display: flex; }
  html:not(.js) .site-nav a,
  html:not(.js) .header-cta { padding-block: 8px; white-space: normal; }
  html:not(.js) .header-cta { margin-block: 4px; } /* fills the 52px row, as the grid's centring did */
}
/* Three tabs on a narrow row: each may shrink, and a tab name breaks rather
   than pushing the next tab off the screen when text is enlarged. */
@media (max-width: 719px) {
  html:not(.js) .site-nav li { flex: 0 1 auto; min-width: 0; }
  html:not(.js) .site-nav a { overflow-wrap: anywhere; }
}
/* Small phones without JavaScript: logo label and enquiry link share one row,
   and the three tabs tighten so each name stays on one line at normal size */
@media (max-width: 419px) {
  html:not(.js) .wordmark .logo { height: 12px; }
  html:not(.js) .header-cta { padding-inline: 8px; font-size: 0.7rem; letter-spacing: 0.02em; }
  html:not(.js) .site-nav a { padding-inline: 10px; letter-spacing: 0.05em; }
  html:not(.js) .site-nav li:first-child a:not([aria-current]) { padding-left: 0; }
}
@media (max-width: 359px) {
  html:not(.js) .site-nav a { padding-inline: 8px; font-size: 0.78rem; letter-spacing: 0.04em; }
}

/* Phone navigation: an unboxed Menu button, then the original
   red sheet of pages and artists. Without JavaScript the page tabs above
   remain visible. All desktop navigation keeps its existing styling. */
.menu-toggle { display: none; }
html.menu-open { overflow: hidden; }
@media (max-width: 719px) {
  :root { --header-h: 56px; }
  .js .site-header {
    position: sticky;
    top: 0;
    height: var(--header-h);
    box-shadow: inset 0 -1px 0 var(--ink);
  }
  .js .site-header__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "mark toggle";
    height: 100%;
    column-gap: 10px;
  }
  .js .site-nav,
  .js .header-cta { display: none; }
  .js .menu-toggle { display: inline-flex; }

  /* Keep the supplied yellow label and logo proportions, with room for
     enlarged Menu/Close text. On phones the label hangs 8px into the gutter. */
  .js .wordmark {
    width: 164px;
    max-width: calc(100% + 8px);
    min-width: 0;
    margin-inline: -8px 0;
    padding-inline: 8px;
  }
  .js .wordmark .logo {
    width: 100%;
    min-width: 0;
    height: auto;
    max-height: 16px;
  }

  .menu-toggle {
    grid-area: toggle;
    position: relative;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    min-width: 88px;
    min-height: 44px;
    padding: 0 0 0 14px;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--paper);
    font-size: 0.875rem;
    font-weight: 550;
    font-variation-settings: "wdth" 96;
    letter-spacing: 0;
    text-transform: none;
    cursor: pointer;
  }
  .menu-toggle::before {
    content: "";
    position: absolute;
    inset: 10px auto 10px 0;
    border-left: 1px solid rgb(240 228 206 / 55%);
  }
  .menu-toggle__icon { position: relative; flex: 0 0 16px; width: 16px; height: 12px; }
  .menu-toggle__icon::before,
  .menu-toggle__icon::after {
    content: "";
    position: absolute;
    left: 0; right: 0;
    height: 1px;
    background: currentColor;
  }
  .menu-toggle__icon::before { top: 1px; }
  .menu-toggle__icon::after { top: 9px; }
  .menu-toggle[aria-expanded="true"] .menu-toggle__icon::before { top: 5px; transform: rotate(45deg); }
  .menu-toggle[aria-expanded="true"] .menu-toggle__icon::after { top: 5px; transform: rotate(-45deg); }
  .menu-toggle:focus-visible {
    outline: 2px solid var(--paper);
    outline-offset: 2px;
    box-shadow: none;
  }

  /* Menu sheet: the three pages in poster type, then every artist */
  .menu-sheet {
    --focus: var(--paper);
    --focus-halo: var(--red);
    position: fixed;
    inset: var(--header-h) 0 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    background-color: var(--red);
    background-image: var(--grain-red);
    border-top: 4px solid var(--yellow); /* yellow trim as on the red panels; a border, so the scrolling menu never covers it */
    color: var(--paper);
  }
  .menu-sheet[hidden] { display: none; }
  .menu-sheet__inner { display: grid; gap: 36px; padding-block: 28px 48px; }
  .menu-sheet ul { margin: 0; padding: 0; list-style: none; }
  .menu-sheet__label {
    margin: 0 0 8px;
    font-family: var(--font-display);
    font-size: 0.8rem;
    font-weight: 750;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
  .menu-sheet__pages a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-block: 2px;
    color: var(--paper);
    font-family: var(--font-display);
    font-size: clamp(2.6rem, 1.2rem + 7vw, 4.2rem);
    font-weight: 900;
    font-variation-settings: "wdth" 62;
    line-height: 0.95;
    text-transform: uppercase;
    text-decoration: none;
  }
  /* the current page carries the poster's ink drop-shade */
  .menu-sheet__pages a[aria-current="page"] { text-shadow: 0.05em 0.05em 0 var(--ink); }
  .menu-sheet__artists {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 16px;
    border-top: 1px solid rgb(240 228 206 / 0.45);
  }
  .menu-sheet__artists a {
    display: flex;
    align-items: center;
    min-height: 52px;
    border-bottom: 1px solid rgb(240 228 206 / 0.45);
    color: var(--paper);
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 850;
    font-variation-settings: "wdth" 115;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    text-decoration: none;
  }
  .menu-sheet a:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; box-shadow: none; }
}
@media (max-width: 719px) and (hover: hover) and (pointer: fine) {
  .menu-sheet a:hover { text-decoration: underline; text-underline-offset: 0.15em; }
}

/* Tablet and desktop: one row, links always visible, no Menu button */
@media (min-width: 720px) {
  .site-header {
    position: sticky;
    top: 0;
    height: var(--header-h);
  }
  .site-header__inner {
    grid-template-columns: 1fr auto;
    grid-template-areas: "mark nav";
    height: 100%;
    column-gap: clamp(16px, 2.2vw, 32px);
  }
  .site-nav { align-self: stretch; }
  .site-nav ul { height: 100%; }
  .site-nav li { display: flex; }
  .site-nav a { min-height: 0; padding: 0 clamp(14px, 1.4vw, 20px); }
  .site-nav li:first-child a:not([aria-current]) { padding-left: clamp(14px, 1.4vw, 20px); }
  /* the tab starts 12px below the band's top edge and runs down into the page */
  .site-nav a[aria-current="page"] { margin-top: 12px; padding-bottom: 12px; }
  .menu-toggle,
  .menu-sheet { display: none !important; }
  /* body is the container the header checks with enlarged text
     (below). Only from 720px: on phones the Menu sheet is position: fixed and
     must stay relative to the screen, which a container would change. */
  body { container: page / inline-size; }
  /* In-page jumps and keyboard focus leave room for the band. With enlarged
     text it may take two rows (96px); at normal text size this is 60px. */
  :root { --header-room: clamp(60px, 60px + (1rem - 16px) * 1000, 96px); }
  html { scroll-padding-top: calc(var(--header-room) + 16px); }
}
/* Narrow tablets: three page tabs plus Message the studio only fit one row
   with tighter spacing, so the header tightens between 720 and 829px (from
   820px the normal spacing fits with room to spare). */
@media (min-width: 720px) and (max-width: 829px) {
  .site-header__inner { column-gap: 12px; }
  .site-nav a, .header-cta { font-size: 0.78rem; letter-spacing: 0.05em; }
  .site-nav a, .site-nav li:first-child a:not([aria-current]) { padding-inline: 10px; }
  .header-cta { padding-inline: 12px; }
}

/* Tablet and desktop with enlarged text: when the logo, the three tabs and
   "Message the studio" no longer fit one row, the band takes two rows, as the
   phone header does without JavaScript: logo and enquiry link on top, page
   tabs below, so the current tab still joins the page. The band stays pinned
   and everything that sits under it moves down with it (--header-h). At
   normal text size this never applies: 48rem - 50px is 718px there, below the
   720px where this layout starts. At 125% text it switches below 910px, at
   150% below 1102px and at 200% below 1486px. */
@container page (width < calc(48rem - 50px)) {
  body > * { --header-h: 96px; }
  .site-header { height: auto; min-height: var(--header-h); }
  .site-header__inner {
    grid-template-columns: 1fr auto;
    grid-template-areas: "mark cta" "nav nav";
    height: auto;
  }
  .site-nav a,
  .header-cta { padding-block: 8px; white-space: normal; }
  .site-nav a { min-height: 44px; padding-inline: 16px; }
  .site-nav li:first-child a:not([aria-current]) { padding-left: 0; }
  .site-nav a[aria-current="page"] { margin-top: 0; padding-bottom: 8px; }
}

/* 5. BUTTONS + LINKS -------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 52px;
  padding: 0 clamp(20px, 2vw, 28px);
  border: 2px solid currentColor;
  border-radius: 0;
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 750;
  font-variation-settings: "wdth" 100;
  letter-spacing: 0.08em; /* same capitals as the header labels */
  line-height: 1.1;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  white-space: normal; /* one line whenever it fits; wraps only if enlarged text can't fit the width */
  text-wrap: balance;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease, border-color 160ms ease, transform 140ms var(--ease-out);
}
.btn:active { transform: scale(0.97); }
.btn--red { background: var(--red); border-color: var(--red); color: var(--paper); }
.btn--line { background: transparent; border-color: var(--ink); color: var(--ink); }
.btn--paper { background: var(--paper); border-color: var(--paper); color: var(--red); }
@media (hover: hover) and (pointer: fine) {
  .btn--red:hover { background: var(--red-deep); border-color: var(--red-deep); }
  .btn--line:hover { background: var(--ink); color: var(--paper); }
  .btn--paper:hover { background: var(--paper-light); border-color: var(--paper-light); color: var(--red); }
}

/* Secondary actions are an underlined link with an arrow, never a second
   box next to the red button. The arrow is decoration only (aria-hidden). */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  min-height: 48px;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 750;
  font-variation-settings: "wdth" 100;
  letter-spacing: 0.08em;
  line-height: 1.1;
  text-transform: uppercase;
  text-decoration: none;
}
.arrow-link__text {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.45em;
}
.arrow-link__arrow { display: inline-block; font-size: 1.15em; transition: transform 200ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .arrow-link:hover { color: var(--red); }
  .arrow-link:hover .arrow-link__arrow { transform: translateX(4px); }
}

.link {
  color: inherit;
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: "wdth" 90;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.28em;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  min-width: 44px;
}
@media (hover: hover) and (pointer: fine) {
  .link:hover { color: var(--red); }
  .on-red .link:hover, .on-ink .link:hover { color: inherit; text-decoration-thickness: 3px; }
}
.actions { display: flex; flex-wrap: wrap; gap: 10px 32px; align-items: center; }
/* On red panels the underlined link is paper, and stays paper on hover */
.on-red .arrow-link { color: var(--paper); }
@media (hover: hover) and (pointer: fine) {
  .on-red .arrow-link:hover { color: var(--paper); }
}
/* Phones: the red button runs the full width, the link sits under it */
@media (max-width: 599px) {
  .actions .btn { flex: 1 1 100%; }
}

/* 6. ARTWORK FRAMES ----------------------------------------------------
   Two frame types, kept deliberately different so a visitor can tell them
   apart at a glance:
     .plate  = Completed tattoo: a photograph in a dark ink mount
     .sheet  = Flash design: a printed paper sheet, double border, red rule  */
.work { margin: 0; }
.work__link {
  display: block;
  color: inherit;
  text-decoration: none;
}
/* Only frames that hold a photo (the link has an href) can be opened */
.work__link[href] { cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.work__frame { position: relative; display: block; overflow: hidden; }

/* Empty frames keep their shape until a photo is added. They must stay truly
   empty (<span class="work__frame"></span>) for :empty to match. */
.work__frame:empty { aspect-ratio: var(--ratio, 4 / 5); box-sizing: content-box; }
.work__img { width: 100%; }
/* Supplied studio clips retain their full portrait frame and native controls. */
.work__video { display: block; width: 100%; height: auto; aspect-ratio: 9 / 16; object-fit: contain; }
.work__video:focus-visible { outline-offset: 4px; }

.plate .work__frame {
  background: var(--ink);
  padding: clamp(6px, 0.9vw, 12px);
}
.plate--fixed .work__img { aspect-ratio: 4 / 5; object-fit: contain; }
.plate--fixed .work__frame:empty { aspect-ratio: 4 / 5; box-sizing: content-box; }
/* Empty tattoo frame: the ink mount with a slightly lighter window */
.plate .work__frame:empty::after {
  content: "";
  position: absolute;
  inset: clamp(6px, 0.9vw, 12px);
  background: #2b2421;
}

.sheet .work__frame {
  background: var(--paper-light);
  /* a slim paper margin: just clear of the 7px double rule (sides and foot)
     and the red head rule (top), so the flash fills the sheet */
  padding: clamp(9px, 1vw, 13px);
  padding-top: clamp(15px, 1.6vw, 20px);
  box-shadow:
    inset 0 0 0 2px var(--ink),
    inset 0 0 0 6px var(--paper-light),
    inset 0 0 0 7px var(--ink);
}
.sheet .work__frame::before {
  content: "";
  position: absolute;
  top: 7px; left: 7px; right: 7px;
  height: clamp(5px, 0.6vw, 8px);
  background: var(--red);
}
/* Phones: the same printed sheet at about half the weight. On a card about
   110px wide the full-size rules (a 7px double rule, a red head rule and a
   paper margin) took a fifth of the width, so here the ink rule, paper gap
   and fine rule make a 4px band, the red rule is 3px and the margin is a
   sliver. */
@media (max-width: 599px) {
  .sheet .work__frame {
    padding: 5px;
    padding-top: 9px;
    box-shadow:
      inset 0 0 0 1.5px var(--ink),
      inset 0 0 0 3px var(--paper-light),
      inset 0 0 0 4px var(--ink);
  }
  .sheet .work__frame::before { top: 4px; left: 4px; right: 4px; height: 3px; }
}
/* 4:5, the shape of the studio's flash sheets (was A-size, which left a
   band of empty paper above and below every sheet) */
.sheet .work__img { aspect-ratio: 4 / 5; object-fit: contain; }
.sheet .work__frame:empty { aspect-ratio: 4 / 5; box-sizing: content-box; }
/* square or wide flash sheets fill the frame (set by dev/gen-artists.py); the viewer shows them whole */
.sheet .work__img--fill { object-fit: cover; }

/* Tap/hover affordance: the frame lifts a touch; focus ring goes on the link */
.work__link:focus-visible { outline-offset: 4px; }
@media (hover: hover) and (pointer: fine) {
  .work__frame { transition: transform 220ms var(--ease-out); }
  .work__link[href]:hover .work__frame { transform: translateY(-3px); }
}
.work__link[href]:active .work__frame { transform: scale(0.99); }

.caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin-top: 10px;
  padding-bottom: 2px;
  font-size: var(--step--1);
  line-height: 1.35;
}
/* Frames carry no kind label ("Flash design", "Completed tattoo"): the user
   removed it. The caption only holds the "Enlarge" cue, so it is hidden
   until the frame holds a photo. */
.work__link:not([href]) .caption { display: none; }
.caption__meta { color: var(--ink-soft); font-style: italic; }
/* "Enlarge" appears automatically once a frame holds a photo (link has href) */
.work__link[href] .caption::after {
  content: "Enlarge";
  margin-left: auto;
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: "wdth" 88;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.25em;
}
@media (max-width: 599px) {
  .work-grid .work__link[href] .caption::after {
    margin-left: 0;
    font-size: 8px;
  }
}

/* 9. ENQUIRY PANEL + FOOTER ------------------------------------------- */
.enquiry {
  position: relative;
  background-color: var(--red);
  background-image: var(--grain-red);
  box-shadow: inset 0 4px 0 var(--yellow); /* yellow trim along the top */
  color: var(--paper);
}
.enquiry__inner {
  display: grid;
  gap: clamp(24px, 3vw, 40px);
  padding-block: clamp(64px, 8vw, 128px);
}
.enquiry__title {
  font-size: clamp(2.6rem, 1.4rem + 6.2vw, 7.4rem);
  font-weight: 900;
  font-variation-settings: "wdth" 60;
  line-height: 0.9;
  text-transform: uppercase;
  max-width: 11ch;
}
.enquiry__body { max-width: 46ch; }
.enquiry__body p { max-width: none; }
.enquiry__handle {
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: "wdth" 96;
}
.enquiry__note { font-size: var(--step--1); }
.enquiry__body .actions { margin-bottom: 1em; }
@media (min-width: 960px) {
  .enquiry__inner {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: end;
  }
}

/* Museum-colophon layout with the studio's original signage type.
   Static information, no new motion or theme: preserve the print identity. */
.site-footer {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-variation-settings: "wdth" 100;
  line-height: 1.4;
}
.site-footer__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  padding-block: clamp(48px, 6vw, 88px) 28px;
}
.site-footer__inner > * { min-width: 0; }
.site-footer__mark {
  width: min(100%, 360px);
  color: var(--yellow);
  margin: 0 0 16px;
}
.site-footer__mark .logo { width: 100%; height: auto; }
.site-footer__label {
  margin-bottom: 20px;
  font-size: 0.85rem;
  font-weight: 500;
  font-variation-settings: "wdth" 100;
  line-height: 1.4;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  text-wrap: wrap;
}
.site-footer__dot {
  display: inline-block;
  width: 0.34em;
  height: 0.34em;
  margin-inline: 0.08em;
  overflow: hidden;
  border-radius: 50%;
  background: currentColor;
  line-height: 1;
  text-indent: -9999px;
  vertical-align: 0.18em;
}
.site-footer__address { font-style: normal; }
.site-footer__address span { display: block; }
.site-footer__level, .site-footer__suburb, .site-footer__daily {
  font-size: 1.05rem;
  font-weight: 400;
}
.site-footer__level { margin-bottom: 8px; }
.site-footer__street {
  font-size: clamp(1.9rem, 1.4rem + 1.4vw, 2.75rem);
  font-weight: 650;
  font-variation-settings: "wdth" 82;
  line-height: 1.15;
  letter-spacing: -0.025em;
  overflow-wrap: anywhere;
}
.site-footer__suburb { margin-top: 12px; }
.site-footer__time {
  max-width: none;
  margin: 0;
  font-size: clamp(1.9rem, 1.4rem + 1.4vw, 2.75rem);
  font-weight: 650;
  font-variation-settings: "wdth" 82;
  line-height: 1.15;
  letter-spacing: -0.025em;
  overflow-wrap: anywhere;
}
.site-footer__daily { margin: 0 0 8px; }
.footer-note {
  grid-column: 1 / -1;
  margin-top: 8px;
  padding-top: 24px;
  border-top: 1px solid rgb(240 228 206 / 0.2);
  font-size: 0.75rem;
  font-weight: 400;
}
.footer-note p { margin: 0; }
/* Explicit single-column composition below 768px; at tablet widths the
   identity occupies its own row, then the two useful details sit together. */
@media (min-width: 768px) {
  .site-footer__inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 4fr);
    column-gap: clamp(40px, 6vw, 88px);
    row-gap: 48px;
  }
  .site-footer__identity { grid-column: 1 / -1; }
}
@media (min-width: 1100px) {
  .site-footer__inner {
    grid-template-columns: minmax(0, 4fr) minmax(0, 5fr) minmax(0, 3.5fr);
    column-gap: 6%;
    row-gap: 56px;
  }
  .site-footer__identity { grid-column: auto; }
}

/* 10. IMAGE VIEWER ----------------------------------------------------
   The open viewer is a page of the catalogue, and the page takes the frame
   type of the artwork on it: a flash design opens on its printed sheet
   (double ink rule, red head rule) filling the screen; a completed tattoo
   opens on the ink mount. Both are opaque, so the site never shows through.
   Zoom and Close are printed at the head (no title: the kind of work is not
   shown), and the folio (Previous, "1 of 3", Next) sits at the foot. Every
   control is a plain word with a 1px hairline under it, never a box or an
   arrow. Clicking the ink closes the viewer (main.js); the paper of a flash
   sheet never does. */
html.viewer-open { overflow: hidden; }
.viewer {
  container: viewer / size;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--ink);
  color: var(--paper);
}
.viewer::backdrop { background: var(--ink); }
.viewer[open] { display: block; }

/* The page. Tattoo (and the default before data-kind is set): the ink mount. */
.viewer__page {
  --rule: 0px;                       /* the red head rule; flash only */
  --pad: clamp(8px, 2vw, 24px);      /* inside the 7px rule band */
  position: relative;
  height: 100%;
  border: 2px solid transparent;
  padding: 5px;                      /* with the border: the 7px rule band */
  overflow: auto;                    /* safety only: 200% text on a short phone */
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(min(55cqh, 14rem), 1fr) auto;
  background: var(--ink);
  color: var(--paper);
}
/* Flash: the printed sheet, with the same rules as .sheet (2px ink, 4px
   paper, 1px ink, red head rule) and the site's print grain on the paper */
.viewer[data-kind="flash"] .viewer__page {
  --rule: clamp(5px, 0.6vw, 8px);
  --focus: var(--ink);               /* yellow on paper would fail, so the ring is ink here */
  --focus-halo: var(--paper-light);
  border-color: var(--ink);
  outline: 1px solid var(--ink);
  outline-offset: -7px;
  background: var(--paper-light) var(--grain-paper);
  color: var(--ink);
}
.viewer[data-kind="flash"] .viewer__page::before {
  content: "";
  position: absolute;
  top: 5px; left: 5px; right: 5px;   /* 7px in, measured from the padding edge */
  height: var(--rule);
  background: var(--red);
}

/* Running head: Zoom and Close alone, one line of type set right, like a
   single-needle line. The kind of work ("Flash design") is not printed (the
   user removed it); the title stays for screen readers only, as the
   dialog's name. Two weights carry the meaning: what you are looking at
   (the page number, pressed Zoom) is set bold; what you can do is a light
   word with a 1px hairline under it, the weight of the sheet's inner fine
   rule. Pressed Zoom doubles its hairline, like the sheet's own double rule. */
.viewer__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 20px;
  padding: calc(var(--rule) + 8px) var(--pad) 0;
}
.viewer__tools { display: flex; align-items: baseline; gap: 0 20px; margin-left: auto; }

/* The four controls: plain words on a bare button, each with one hairline */
.viewer .viewer__word {
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font-size: var(--step-0);
  font-weight: 400;
  font-variation-settings: "wdth" 82;
  letter-spacing: 0;
  line-height: 1.2;
  text-transform: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;                 /* quick double taps on Next never paint a selection */
  touch-action: manipulation;        /* nor read as double-tap-to-zoom */
  transition: transform 160ms var(--ease-out);
}
/* Each word sits flush to its own side of the 44px tap area, so the words
   start and end exactly on the plate's left and right edges. A press scales
   from that same side, so the word never drifts off the edge. */
.viewer__tools .viewer__word, .viewer .viewer__word--next { justify-content: flex-end; transform-origin: right center; }
.viewer .viewer__word--prev { justify-content: flex-start; transform-origin: left center; }
/* The word's box is trimmed to its capitals and baseline, so it sits
   optically centred in the 44px tap area and can be aligned to the plate.
   The padding takes the box down to the foot of the hairline, and the
   negative margin gives that room back, so the layout doesn't move. */
.viewer .viewer__word .arrow-link__text {
  text-box: trim-both cap alphabetic;
  padding-bottom: calc(0.3em + 1px);
  margin-bottom: calc(-0.3em - 1px);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: none;
  text-underline-offset: 0.3em;
}
/* Hover and press only weight the hairline; red is kept for the kind of
   work and for pressed Zoom */
@media (hover: hover) and (pointer: fine) {
  .viewer .viewer__word:hover { color: inherit; }
  .viewer .viewer__word:hover .arrow-link__text { text-decoration-thickness: 2px; }
}
/* A press gives way slightly, the same feedback as the site's buttons (the
   tap highlight is off, so this is what a touch sees). Pointer presses only:
   Space on a focused word pages without a dip, like Enter. */
.viewer .viewer__word:active:not(:focus-visible) { transform: scale(0.97); }
.viewer .viewer__word:active .arrow-link__text { text-decoration-thickness: 2px; }
/* Pressed Zoom is inked in: the title's weight, and the hairline doubles.
   The narrower width keeps the bold word exactly as wide as the light one,
   so nothing on the line moves when it is pressed. */
.viewer .viewer__word[aria-pressed="true"] {
  font-weight: 700;
  font-variation-settings: "wdth" 73;
}
.viewer .viewer__word[aria-pressed="true"] .arrow-link__text {
  text-decoration-style: double;
  text-decoration-thickness: 1px;
}
.viewer[data-kind="flash"] .viewer__word[aria-pressed="true"] { color: var(--red); }
/* Keyboard focus: a 2px ring round the word and its hairline, with the same
   3px of air on every side, however the word sits in its 44px tap area.
   Words on the plate's edges stay 3px clear of the sheet's fine rule. */
.viewer .viewer__word:focus-visible { outline: none; box-shadow: none; }
.viewer .viewer__word:focus-visible .arrow-link__text {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* The plate: placed on the page with no frame of its own, centred between
   the running head and the folio line, so any spare paper is shared evenly
   above and below it. */
.viewer__stage {
  position: relative;
  overflow: auto;
  overscroll-behavior: contain;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  place-items: center;
  margin: 8px var(--pad);   /* margin, not padding, so a zoomed plate is clipped square on all four sides */
  touch-action: pan-y pinch-zoom;
}
.viewer.is-zoomed .viewer__stage { touch-action: pan-x pan-y pinch-zoom; }
.viewer__stage:focus-visible { outline-offset: -4px; }
.viewer__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  cursor: zoom-in;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
}
/* Zoomed, the picture is dragged to look round it (main.js); a click that
   doesn't move still zooms back out */
.viewer.is-zoomed .viewer__stage { place-items: start; -webkit-user-select: none; user-select: none; }
.viewer.is-zoomed .viewer__img {
  max-width: none;
  max-height: none;
  width: min(1600px, 220%);
  cursor: grab;
}
.viewer.is-panning .viewer__stage, .viewer.is-panning .viewer__img { cursor: grabbing; }

/* Foot: the caption (only when there is one), then the folio line */
.viewer__foot { padding: 0 var(--pad) 12px; }
.viewer__desc {
  margin: 0;
  padding-top: 2px;
  max-width: 60ch;
  font-family: var(--font-text);
  font-size: var(--step--1);
  font-style: italic;
  line-height: 1.4;
}
.viewer__desc:empty { display: none; }
.viewer[data-kind="flash"] .viewer__desc { color: var(--ink-soft); }
.viewer__ref { color: var(--yellow); font-family: var(--font-display); font-style: normal; font-weight: 700; font-variation-settings: "wdth" 92; }
.viewer[data-kind="flash"] .viewer__ref { color: var(--red); }
.viewer__controls {
  display: grid;
  grid-template-columns: 1fr auto 1fr;   /* the page number sits centred under the plate */
  align-items: baseline;                 /* Previous, the page number and Next on one baseline */
  column-gap: 16px;
}
.viewer__count {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 700;
  font-variation-settings: "wdth" 80;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.viewer__word--prev { justify-self: start; }
.viewer__word--next { justify-self: end; }
/* One picture: no folio line, the plate gets the room */
.viewer__controls:has(> [data-viewer-prev][hidden]) { display: none; }

/* Narrow screens and enlarged text */
@container viewer (width < 22rem) {
  .viewer__bar, .viewer__tools { column-gap: 16px; }
}
/* Enlarged text on a phone: the folio line won't hold all three, so the
   page number takes its own centred line, Previous stays left and Next
   stays right. */
@container viewer (width < 20rem) {
  .viewer__controls { display: flex; flex-wrap: wrap; justify-content: space-between; }
  .viewer__count { flex: 1 0 100%; order: -1; text-align: center; }
  .viewer__word--next { margin-left: auto; }
}

/* A wide screen that keeps the stacked layout (a square or 4:3 screen, or
   enlarged text): the page is only as wide as the plate needs, about 144px
   of furniture off the height at 4:5, and lies on the ink table, as it
   does on landscape screens */
@container viewer (width >= 40rem) and (aspect-ratio > 4/5) {
  .viewer__page {
    width: min(100cqw - 24px, max(0.8 * (100cqh - 168px) + 2 * (7px + var(--pad)), 24rem));
    height: calc(100cqh - 24px);
    margin: 12px auto;
  }
}

/* Landscape screens: the sheet lies on the ink table (clicking the ink
   closes) and the furniture moves into the side margins, so the plate gets
   the full height. The margins work like a spread: Previous down the left
   margin; Zoom and Close, the page number and Next down the right. The
   sheet keeps the site's flash sheet proportion (1 to
   1.414) turned landscape, and is only widened when the plate and both
   margins need more room. Below 64rem this layout is used only on short,
   wide screens (a phone turned sideways, a laptop at 200% zoom), where it
   gives a bigger plate than the stacked layout. */
@container viewer (aspect-ratio >= 7/5) and ((width >= 64rem) or ((width >= 45rem) and (aspect-ratio >= 3/2)) or ((width >= 40rem) and (aspect-ratio >= 16/9))) {
  .viewer__page {
    --gap: clamp(24px, 2.5vw, 40px);
    --margin: 10rem;                   /* narrowest margin that holds Zoom and Close, or Previous */
    --pt: calc(7px + var(--rule) + 22px);  /* 24px of paper between the head rule and the capitals, as on phones */
    --pi: calc(7px + var(--pad));
    --pb: 23px;
    width: min(100cqw - 24px, max((100cqh - 24px) * 1.4142, 0.8 * (100cqh - 84px) + 2 * (var(--margin) + var(--gap)) + 2 * (7px + var(--pad))));
    height: calc(100cqh - 24px);
    margin: 12px auto;
    padding: var(--pt) var(--pi) var(--pb);
    grid-template-columns: minmax(var(--margin), 1fr) minmax(0, 3fr) minmax(var(--margin), 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto auto;
    column-gap: var(--gap);
    row-gap: 0;
  }
  .viewer__bar, .viewer__foot, .viewer__controls { display: contents; }
  /* The stage lies under the furniture across the whole sheet, out to the
     rules, so the ink round a tattoo photo closes wherever it is clicked;
     its padding keeps the plate in the middle column */
  .viewer__stage {
    grid-area: 1 / 1 / -1 / -1;
    place-items: center;
    margin: calc(-1 * var(--pt)) calc(-1 * var(--pi)) calc(-1 * var(--pb));
    padding: var(--pt) calc(var(--pi) + max(var(--margin), (100% - 2 * var(--gap)) / 5) + var(--gap)) var(--pb);
  }
  .viewer__tools, .viewer__desc, .viewer__count, .viewer__word--prev, .viewer__word--next { position: relative; z-index: 1; }
  /* The line is ruled to the plate: Zoom and Close hang from the plate's
     top edge (capitals on it), and the hairlines under Previous and Next lie
     on its bottom edge. The 44px tap areas reach past the line into the
     margin paper. */
  .viewer__tools {
    grid-area: 1 / 3; align-self: start; justify-self: end;
    font-family: var(--font-display); font-size: var(--step-0);  /* so 1cap is the words' cap height */
    margin: calc((1cap - 44px) / 2) 0 0;
  }
  .viewer__desc { grid-area: 2 / 1; align-self: start; margin-top: 8px; }
  .viewer__count { grid-area: 3 / 3; justify-self: end; }
  .viewer__word--prev { grid-area: 4 / 1; justify-self: start; }
  .viewer__word--next { grid-area: 4 / 3; justify-self: end; }
  .viewer__word--prev, .viewer__word--next { align-self: end; margin-bottom: calc(0.3em + 1px + (1cap - 44px) / 2); }
  .viewer.is-zoomed .viewer__stage { grid-area: 2 / 1 / 3 / -1; margin: 0 0 12px; padding: 0; }
  .viewer.is-zoomed .viewer__desc { display: none; }
}

/* Forced colours drop the inset rules and the fills, so draw them as borders */
@media (forced-colors: active) {
  .viewer .viewer__page,
  .viewer[data-kind="flash"] .viewer__page { border-color: CanvasText; background-image: none; }
  .viewer[data-kind="flash"] .viewer__page::before { height: 0; background: none; border-top: var(--rule) solid CanvasText; }
}

/* 7. HOME SECTIONS ---------------------------------------------------- */

/* 7a. Opening poster ------------------------------------------------- */
.opening { position: relative; overflow-x: clip; }
.opening__track { position: relative; }
.opening__stage { position: relative; }
.opening__flood { display: none; }
.opening__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr); /* phones: never wider than the screen, even with enlarged text */
  grid-template-areas: "poster" "intro" "plate";
  gap: clamp(20px, 3vw, 40px);
  padding-block: clamp(20px, 4vw, 40px) clamp(48px, 7vw, 88px);
}

/* Heading: a direct, typeset title in the logo red. The line wrapper is what
   the scroll scenes move; the title inside carries the load wipe. */
.poster {
  grid-area: poster;
  position: relative;
  z-index: 1;
  color: var(--red);
}
.poster__line { display: block; }
.poster__title {
  max-width: 9ch;
  font-size: 3.5rem;
  font-weight: 900;
  font-variation-settings: "wdth" 60;
  line-height: 0.84;
  letter-spacing: 0;
  text-transform: uppercase;
}
@media (min-width: 600px) { .poster__title { font-size: 5.75rem; } }
@media (min-width: 960px) { .poster__title { font-size: 7.5rem; } }
@media (min-width: 1440px) { .poster__title { font-size: 8.5rem; } }

.opening__intro { grid-area: intro; position: relative; z-index: 4; }
.opening__lede {
  font-size: var(--step-1);
  font-weight: 500;
  line-height: 1.45;
  max-width: 34ch;
  margin-bottom: 20px;
}
.opening__plate {
  grid-area: plate;
  position: relative;
  z-index: 3;
  width: min(100%, 440px);
  justify-self: end;
}
.opening__plate .caption { transition: color 240ms ease; }
.opening__plate--video { --opening-aspect: 0.5625; }

@media (min-width: 600px) and (max-width: 959px) {
  .opening__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "poster poster" "intro plate";
    align-items: start;
  }
  .opening__plate { width: 100%; }
}

@media (min-width: 960px) {
  .opening__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "poster plate" "intro plate";
    /* equal rows: the logo sits just above the middle and the intro just
       below it, so the pair balances against the tall plate */
    grid-template-rows: 1fr 1fr;
    align-content: center;
    column-gap: clamp(32px, 4vw, 72px);
    row-gap: clamp(20px, 3vh, 40px);
    min-height: calc(100svh - var(--header-h));
    padding-block: clamp(24px, 5vh, 56px);
  }
  .poster { align-self: end; }
  .opening__intro { align-self: start; }
  .opening__plate {
    align-self: center;
    width: min(100%, calc((100svh - var(--header-h) - 150px) * var(--opening-aspect, 0.8)));
  }
}

/* Pinned version (desktop, motion allowed). Natural scrolling: the stage is
   simply sticky inside a taller track. */
@media (min-width: 960px) and (min-height: 600px) {
  .motion .opening__track { height: 250svh; }
  .motion .opening__stage {
    position: sticky;
    top: var(--header-h);
    height: calc(100svh - var(--header-h));
    overflow: hidden;
  }
  .motion .opening__grid { height: 100%; min-height: 0; }
  .motion .opening__flood {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 2;
    background-color: var(--red);
    background-image: var(--grain-red);
    transform-origin: 0 0;
    opacity: 0;
    pointer-events: none;
  }
  .motion .opening__plate { z-index: 3; }
  .motion .opening__track.is-static { height: auto; }
  .motion .opening__track.is-static .opening__stage { position: relative; top: auto; height: auto; overflow: visible; }
  .motion .opening__track.is-static .opening__flood { display: none; }
  .opening.is-flooded .opening__plate .caption { color: var(--paper); }
  .opening.is-flooded .opening__plate .caption__meta { color: var(--paper); }
  .opening.is-flooded .opening__plate { --focus: var(--paper); --focus-halo: var(--ink); }
}

/* 7b. Selected work --------------------------------------------------- */
.selected__band {
  background-color: var(--red);
  background-image: var(--grain-red);
  box-shadow: inset 0 4px 0 var(--yellow); /* yellow trim along the top */
  color: var(--paper);
}
.selected__head {
  display: grid;
  gap: 16px;
  padding-block: clamp(40px, 6vw, 88px) clamp(40px, 5vw, 72px);
}
.selected__title {
  font-size: clamp(2.8rem, 1.6rem + 6vw, 7.6rem);
  font-weight: 900;
  font-variation-settings: "wdth" 60;
  line-height: 0.88;
  text-transform: uppercase;
}
.selected__head p { max-width: 46ch; }
@media (min-width: 960px) {
  .selected__head { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: end; }
}

.selected__grid {
  display: grid;
  gap: clamp(36px, 5vw, 72px) clamp(16px, 2.4vw, 36px);
  padding-top: clamp(40px, 6vw, 96px);
}
.selected__grid .sel { min-width: 0; }
.sel--c { width: 78%; justify-self: end; }
.sel--d { width: 86%; }
.sel--e { width: 78%; justify-self: end; }
@media (min-width: 600px) {
  .selected__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  .sel--a { grid-row: span 2; }
  .sel--c, .sel--d, .sel--e { width: auto; justify-self: stretch; }
  .sel--c { width: 78%; justify-self: center; }
}
@media (min-width: 960px) {
  .selected__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sel--a { grid-column: 1 / span 6; grid-row: 1 / span 2; }
  .sel--b { grid-column: 8 / span 5; grid-row: 1; margin-top: clamp(24px, 4vw, 72px); }
  .sel--c { grid-column: 9 / span 3; grid-row: 2; width: auto; justify-self: stretch; }
  .sel--d { grid-column: 2 / span 4; grid-row: 3; margin-top: clamp(24px, 4vw, 64px); }
  .sel--e { grid-column: 7 / span 4; grid-row: 3; }
}

.inline-link { color: var(--red); text-decoration-thickness: 1px; text-underline-offset: 0.2em; padding-block: 11px; }
@media (hover: hover) and (pointer: fine) { .inline-link:hover { text-decoration-thickness: 2px; } }

/* 7d. Flash preview --------------------------------------------------- */
.flashpre {
  overflow-x: clip;
  background: var(--paper-deep);
  border-block: 2px solid var(--ink);
}
.flashpre__track, .flashpre__stage { position: relative; }
.flashpre__grid {
  display: grid;
  gap: clamp(28px, 4vw, 56px);
  padding-block: var(--section);
}
.flashpre__title {
  margin-bottom: 18px;
  color: var(--red);
  font-size: clamp(2.6rem, 1.5rem + 5vw, 6.2rem);
  font-weight: 900;
  font-variation-settings: "wdth" 58;
  line-height: 0.88;
  text-transform: uppercase;
}
.flashpre__text p { max-width: 40ch; }
.flashpre__text > p:first-of-type { font-weight: 500; line-height: 1.45; }
.flashpre__text .arrow-link { margin-top: 4px; }
.flashpre__sheets {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 16px;
}
.flashpre__item { min-width: 0; }
.flashpre__item .work { transform-origin: 50% 60%; }

/* Phones: a swipeable row, contained so the page itself never scrolls sideways */
@media (max-width: 599px) {
  .flashpre__sheets {
    grid-auto-flow: column;
    grid-auto-columns: 72%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    margin-inline: calc(var(--gutter) * -1);
    padding: 8px var(--gutter) 16px;
    scroll-padding-inline: var(--gutter);
  }
  .flashpre__item { scroll-snap-align: start; }
}
@media (min-width: 600px) {
  .flashpre__sheets { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .flashpre__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    align-items: center;
    column-gap: clamp(40px, 5vw, 96px);
  }
  .flashpre__sheets { gap: clamp(16px, 2vw, 32px); }
}
@media (min-width: 960px) and (min-height: 600px) {
  .motion .flashpre__track { height: 230svh; }
  .motion .flashpre__stage {
    position: sticky;
    top: var(--header-h);
    height: calc(100svh - var(--header-h));
    overflow: hidden;
    display: grid;
    align-items: center;
  }
  .motion .flashpre__grid { padding-block: 24px; }
  .motion .flashpre__track.is-static { height: auto; }
  .motion .flashpre__track.is-static .flashpre__stage { position: relative; top: auto; height: auto; overflow: visible; display: block; }
  .motion .flashpre__track.is-static .flashpre__grid { padding-block: var(--section); }
  .motion .flashpre__sheets { max-width: calc((100svh - var(--header-h) - 200px) * 0.8 * 3 + 64px); justify-self: center; width: 100%; }
}

/* Instagram line in each artist profile: the handle as an underlined link,
   or "Instagram" with its TBC tag until the studio supplies it. Every line is
   at least 44px tall, so all profiles line up either way. */
.artist-ig {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 8px;
  min-height: 44px;
  margin: 0;
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  font-variation-settings: "wdth" 88;
}
.artist-ig a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.35em;
  transition: color 160ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .artist-ig a:hover { color: var(--red); }
}
.artist-ig .tbc { font-size: 0.68rem; padding: 0 0.25em; }

.portrait {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--ink);
  padding: clamp(6px, 0.9vw, 12px);
}
.portrait img { width: 100%; }
/* Empty portrait frame, replaced by an <img> once a portrait is approved */
.portrait__empty { display: block; aspect-ratio: 3 / 4; background: #2b2421; }

/* 8. ARTISTS & FLASH SECTIONS ----------------------------------------- */
@media (min-width: 720px) {
  html:has(.page-artists) { scroll-padding-top: calc(var(--header-room) + var(--jump-h) + 16px); }
}
@media (max-width: 719px) {
  html:has(.page-artists) { scroll-padding-top: calc(var(--jump-h) + 16px); }
  html.js:has(.page-artists) { scroll-padding-top: calc(var(--header-h) + var(--jump-h) + 16px); }
}

.page-head { padding-block: clamp(28px, 5vw, 72px) clamp(32px, 5vw, 64px); }
.page-head__grid { display: grid; gap: clamp(20px, 3vw, 40px); }
.page-title {
  color: var(--red);
  font-size: clamp(3rem, 1.2rem + 9vw, 10.5rem);
  font-weight: 900;
  font-variation-settings: "wdth" 56;
  line-height: 0.84;
  text-transform: uppercase;
}
.page-title__ink { display: inline-block; }
.page-head__lede { font-size: var(--step-1); font-weight: 500; line-height: 1.45; max-width: 38ch; }

@media (min-width: 960px) {
  .page-head__grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: end; column-gap: 5%; }
}

/* Sticky artist menu: a quiet rail of names (one link per artist profile).
   One row at every width, exactly --jump-h tall, directly under the header.
   The rail is the ink rule along its foot. Names are plain words; the
   artist in view is inked in (bolder, like pressed Zoom in the viewer,
   without moving its neighbours) and a short red rule stands on the rail
   under it, like the head rule on a flash sheet. On phones it is a wheel
   (below). On wider screens, if enlarged text makes the names overflow,
   the row scrolls sideways and fades an edge while names are hidden past
   it (main.js sets .has-more-before/-after). */
.jumpnav {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--jump-h);
  background-color: var(--paper);
  background-image: var(--grain-paper); /* same paper as the header's current tab */
  /* the rail: the same 2px ink rule as the header's and the profiles',
     drawn just below the menu so a profile's own rule lands exactly on it */
  box-shadow: 0 2px 0 var(--ink);
}
.jumpnav .wrap { height: 100%; padding-inline: 0; }
.jumpnav__list {
  --pad: 9px;    /* each name's side padding, part of its tap area (all twelve fit from 768px) */
  --fade: 3rem;  /* the paper fade at an edge the names run past (enlarged text) */
  position: relative; /* main.js measures the names from here */
  display: flex;
  justify-content: space-between; /* wide screens: the names span the page's text measure */
  height: 100%;
  margin: 0;
  padding: 0 calc(var(--gutter) - var(--pad)); /* the first and last names line up with the page's text edges */
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-padding-inline: var(--fade); /* names scrolled or tabbed into view stop clear of the fades */
  scrollbar-width: none;
}
.jumpnav__list::-webkit-scrollbar { display: none; }
/* A fade is a mask, not motion, so it shows with reduced motion too. A row
   that fits has no mask at all. */
.jumpnav__list.has-more-before { --fade-start: var(--fade); }
.jumpnav__list.has-more-after { --fade-end: var(--fade); }
.jumpnav__list:is(.has-more-before, .has-more-after) {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--fade-start, 0px), #000 calc(100% - var(--fade-end, 0px)), transparent);
  mask-image: linear-gradient(to right, transparent, #000 var(--fade-start, 0px), #000 calc(100% - var(--fade-end, 0px)), transparent);
}
.jumpnav li { flex: none; }
.jumpnav a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px; /* short names (EL) still get a 44px square to tap */
  height: 100%;
  padding: 0 var(--pad);
  color: var(--ink-soft);
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 0.7rem + 0.5vw, 1.1rem); /* a little larger on wide screens, so the rail doesn't look underweight */
  font-weight: 550;
  font-variation-settings: "wdth" 90;
  line-height: 1.2; /* the name's box, and so its focus ring, is one line tall */
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent; /* the press dip is the feedback (section 11) */
  /* The menu is always on screen, so focusing a name never scrolls the page.
     Without this the page's scroll padding, which keeps room for the pinned
     bars, reads the pinned menu as hidden, and every Tab through the names
     pulled the page up about 430px (and changed the artist in view). */
  scroll-margin-top: calc(-1 * (var(--header-h) + var(--jump-h) + 16px));
}
/* The artist in view: inked in. At wdth 86 the bold name is never narrower
   than the plain one (at most a few px wider), so a hidden bold copy under each
   name can hold its width: marked or not, no name along the row moves when
   the artist in view changes. The copy is not read aloud (visibility:
   hidden, and an empty alt text). */
.jumpnav a[aria-current="location"] {
  color: var(--ink);
  font-weight: 750;
  font-variation-settings: "wdth" 86;
}
.jumpnav__name {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
}
.jumpnav__name::after {
  content: attr(data-name);
  content: attr(data-name) / "";
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: 750;
  font-variation-settings: "wdth" 86;
}
/* The short red rule, standing on the rail under the name (never wider than
   the name, so EL's is EL's width). A border, not a background, so forced
   colours keep it. */
.jumpnav a[aria-current="location"] .jumpnav__name::before {
  content: "";
  position: absolute;
  top: calc(50% + var(--jump-h) / 2 - 3px);
  left: 50%;
  width: min(1.2em, 100%);
  transform: translateX(-50%);
  border-top: 3px solid var(--red);
}
/* Hover draws the viewer's hover hairline (2px) under the word */
@media (hover: hover) and (pointer: fine) {
  .jumpnav a:hover { color: var(--ink); }
  .jumpnav a:not([aria-current]):hover {
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-decoration-skip-ink: none;
    text-underline-offset: 0.3em;
  }
}
/* Keyboard focus: a 2px ring round the word with 3px of air (the viewer's
   ring), which stays inside the row so its scrolling box cannot clip it */
.jumpnav a:focus-visible { outline: none; box-shadow: none; }
.jumpnav a:focus-visible .jumpnav__name {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}
@media (min-width: 720px) {
  .jumpnav { top: var(--header-h); }
}
@media (max-width: 719px) {
  .js .jumpnav { top: var(--header-h); } /* below the slim sticky phone header */
}
/* Phones: Deep Lens turns a horizontal wheel above the fixed red rule.
   Equal cells and a 64px rail grow with enlarged text. Only the labels
   turn (section 11); links and snap positions stay still and fully tappable.
   The em breakpoint also respects the browser's default text size. */
@media (max-width: 47.99em) {
  :root { --jump-h: max(64px, 4rem); }
  .jumpnav {
    box-shadow: 0 1px 0 rgb(27 23 21 / 45%);
    background-image:
      var(--grain-paper),
      linear-gradient(to right,
        var(--paper) 0%, var(--paper) 24%,
        var(--paper-light) 46%, var(--paper-light) 54%,
        var(--paper) 76%, var(--paper) 100%);
  }
  .jumpnav__list {
    justify-content: flex-start;
    padding: 0 50%; /* the first and last names can reach the middle */
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 0;
  }
  /* Shape explains distance from the centre; phone lettering is not faded. */
  .jumpnav__list,
  .jumpnav__list:is(.has-more-before, .has-more-after) {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .jumpnav li {
    flex: 0 0 max(96px, 6rem);
    width: max(96px, 6rem);
    min-width: 44px;
    scroll-snap-align: center;
  }
  .jumpnav a {
    width: 100%;
    min-height: 44px;
    padding-inline: 4px;
    font-size: 1.1rem;
    letter-spacing: -0.01em;
  }
  .jumpnav a:not([aria-current]) { color: var(--ink-soft); font-weight: 450; }
  .jumpnav__name { transform-origin: center; }
  /* The fixed marker sits close to the name, separate from the bottom rail. */
  .jumpnav::after {
    content: "";
    position: absolute;
    bottom: calc(50% - 1.1rem);
    left: 50%;
    width: 2rem;
    transform: translateX(-50%);
    border-top: 3px solid var(--red);
    pointer-events: none;
  }
  .jumpnav a[aria-current="location"] .jumpnav__name::before { content: none; }
}

/* Artist section. A jump to a profile lands its ink rule right on the
   menu's rail (one line, not two), so it takes back the 16px of air the
   page's scroll-padding leaves. With enlarged text the padding also allows
   for a two-row header (--header-room, from 720px); a profile gives back
   whatever the header isn't using. */
.artist {
  padding-block: clamp(40px, 6vw, 88px);
  scroll-margin-top: calc(var(--header-h) - var(--header-room, var(--header-h)) - 16px);
}
.artist + .artist { border-top: 2px solid var(--ink); }
/* Just after a jump the profile's pieces are still settling in (their
   entrance transforms). If the browser anchored the scroll to one of them
   it would nudge the page 3 to 8px (seen from 720 to 959px), parting the
   profile's rule from the rail again, so they never anchor it. */
.motion .artist [data-reveal] { overflow-anchor: none; }
.artist:last-of-type { padding-bottom: var(--section); }
.artist__grid { display: grid; gap: clamp(36px, 5vw, 64px); }
.artist__profile { display: grid; gap: 20px; align-content: start; }
.artist__portrait { width: min(40%, 150px); }
@media (min-width: 480px) { .artist__portrait { width: min(100%, 360px); } }
.artist__role { margin-bottom: 4px; font-family: var(--font-display); font-weight: 700; font-variation-settings: "wdth" 92; }
.artist__name {
  margin-bottom: 14px;
  color: var(--red);
  font-size: clamp(4rem, 2.6rem + 6vw, 8.5rem);
  font-weight: 900;
  font-variation-settings: "wdth" 56;
  line-height: 0.8;
  text-transform: uppercase;
}
/* These three profile names use their supplied title case. */
.artist__name:where(#sand-name, #chris-name, #courtney-name) { text-transform: none; }
.artist__styles { font-size: var(--step-1); line-height: 1.4; }
.artist__links { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; margin-top: 8px; }
@media (min-width: 480px) and (max-width: 959px) {
  .artist__profile { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); align-items: end; }
}
@media (min-width: 960px) {
  .artist__grid { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); column-gap: clamp(40px, 5vw, 88px); align-items: start; }
  .artist__profile {
    position: sticky;
    top: calc(var(--header-h) + var(--jump-h) + 24px);
  }
  .artist__profile.is-static { position: relative; top: auto; }
  /* portrait height = screen - sticky bars - gaps - the measured text block (--info-h);
     the width follows the photo's own shape (--ratio, 3 / 4 while empty) */
  .artist__portrait { width: min(100%, calc((100svh - var(--header-h) - var(--jump-h) - 116px - var(--info-h, 460px)) * var(--ratio, 3 / 4))); min-width: 150px; }
  .artist__name { font-size: clamp(3.6rem, 1.6rem + 3.6vw, 6.4rem); }
}

.work-group + .work-group { margin-top: clamp(56px, 7vw, 112px); }
.work-group__head { margin-bottom: clamp(20px, 3vw, 36px); }
.work-group__title {
  margin-bottom: 10px;
  font-size: clamp(2.2rem, 1.4rem + 3.6vw, 4.6rem);
  font-weight: 900;
  font-variation-settings: "wdth" 60;
  line-height: 0.9;
  text-transform: uppercase;
}
.work-group--tattoo .work-group__title { color: var(--ink); }
.work-group__band {
  margin-bottom: clamp(24px, 3vw, 40px);
  padding: clamp(22px, 3vw, 40px) clamp(18px, 3vw, 40px);
  background-color: var(--red);
  background-image: var(--grain-red);
  box-shadow: inset 0 4px 0 var(--yellow); /* yellow trim along the top */
  color: var(--paper);
}
.work-group__band p { max-width: 52ch; }

.work-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 48px) clamp(12px, 2vw, 32px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.work-grid > li { min-width: 0; }
/* orderly asymmetry: the right-hand column of completed tattoos sits lower */
@media (min-width: 600px) {
  .work-grid--tattoo { padding-bottom: 56px; }
  .work-grid--tattoo > li:nth-child(even) { translate: 0 56px; }
}
@media (max-width: 599px) {
  .work-grid { gap: 18px 8px; }
  .work-grid .caption { font-size: 0.78rem; }
  /* Flash on phones: one swipeable row of big sheets (each about 80% of the
     screen, the next one peeking in from the edge) instead of three small
     ones. The row runs out to the screen edges; the page gutter becomes its
     padding, so the first sheet still lines up with the text. */
  .work-grid--flash {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: min(80%, 22rem);
    gap: 12px;
    margin-inline: calc(-1 * var(--gutter));
    padding-inline: var(--gutter);
    padding-bottom: 6px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .work-grid--flash::-webkit-scrollbar { display: none; }
  .work-grid--flash > li { scroll-snap-align: start; }
  .work-grid--flash .caption { font-size: var(--step--1); }
  /* Completed tattoos on phones: two across and the last odd one centred
     below, so all three fit on one screen at about 1.5 times the size (less
     than flash, which gets the swipe row) */
  .work-grid--tattoo { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 10px; max-width: 26rem; } /* the cap keeps all three on one screen on the widest phones */
  .work-grid--tattoo > li:last-child:nth-child(odd) { grid-column: 1 / -1; justify-self: center; width: calc(50% - 5px); }
}

/* 8b. Enquiries page: brief form and Instagram handoff ---------------- */
.page-head__intro .actions { margin-top: 24px; }
.enquire__note { margin-top: 14px; font-size: var(--step--1); color: var(--ink-soft); }
.enquire { padding-top: clamp(40px, 5vw, 80px); } /* sits close under the page heading */
.enquire__grid { display: grid; gap: clamp(40px, 6vw, 72px); }
.enquire__title + .enquire__note { margin: -4px 0 12px; } /* the TBC tag qualifies the whole list */
.enquire__title {
  margin-bottom: 14px;
  color: var(--red);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3.4rem);
  font-weight: 900;
  font-variation-settings: "wdth" 58;
  line-height: 0.9;
  text-transform: uppercase;
}
/* The list reads like the studio details beside it: one ruled row each */
.enquire__list { margin: 0; padding: 0; list-style: none; }
.enquire__list li {
  padding-block: 14px;
  border-top: 1px solid rgb(27 23 21 / 0.28);
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 750;
  font-variation-settings: "wdth" 90;
}
@media (min-width: 960px) {
  .enquire__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 8.33%; }
}

/* Visible attribution stays separate from the artwork's Enlarge link. */
.work-credit {
  margin-top: 6px;
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 650;
  line-height: 1.4;
}
.work-credit a { display: inline-flex; align-items: center; min-height: 44px; }

/* Short studio brief: the existing paper, ink and ruled type hierarchy. */
#enquiry-form { scroll-margin-top: calc(var(--header-h) + 24px); }
.enquire__routing { margin-top: 20px; font-size: var(--step-0); }
.enquire__intro { max-width: 42rem; margin-bottom: 24px; }
.enquiry-app { align-items: start; }
.enquiry-form__legend { margin: 0 0 20px; color: var(--ink-soft); font-size: var(--step--1); }
.enquiry-form__fields { display: grid; gap: 22px 20px; }
.enquiry-field label, .enquiry-preview label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 750;
  line-height: 1.4;
}
.enquiry-field label span { font-weight: 450; color: var(--ink-soft); }
.enquiry-field input, .enquiry-field select, .enquiry-field textarea, .enquiry-preview textarea {
  display: block;
  width: 100%;
  min-width: 0;
  min-height: 52px;
  border: 1px solid var(--ink-soft);
  border-radius: 0;
  padding: 12px;
  color: var(--ink);
  background: var(--paper-light);
  font: 1rem/1.5 var(--font-text);
}
.enquiry-field select { padding-right: 32px; }
.enquiry-field textarea, .enquiry-preview textarea { resize: vertical; }
.enquiry-field input::placeholder, .enquiry-field textarea::placeholder, .enquiry-preview textarea::placeholder { color: var(--ink-soft); opacity: 1; }
.enquiry-form__submit { margin-top: 28px; }
.enquiry-form__status { margin-top: 16px; color: var(--red); font-family: var(--font-display); font-size: 1rem; font-weight: 650; }
.enquiry-form__status:empty { margin-top: 0; }
.enquiry-preview { border-top: 3px solid var(--red); padding-top: 20px; }
.enquiry-preview textarea { font-size: .95rem; }
.enquiry-form button:disabled { cursor: wait; opacity: .65; }
@media (min-width: 600px) {
  .enquiry-form__fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .enquiry-field--wide { grid-column: 1 / -1; }
}
@media (min-width: 960px) {
  .enquiry-app { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); column-gap: 6%; }
}
@media (max-width: 599px) {
  .enquiry-form__submit { width: 100%; }
}

/* 11. MOTION ------------------------------------------------------------
   Every rule below needs html.motion, which the head script only sets when
   the device allows motion. Without it, nothing here applies and all
   content is simply visible.
   Effects are deliberately varied:
     wipe-up / wipe-down / wipe-left / wipe-right : print-pull masks on artwork
     ink    : a left-to-right roller wipe on headings
     rise   : small lift for supporting text
     deal   : flash sheets and cards settle like paper dealt onto a table
     unmask : a red panel slides off a portrait
   ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .motion [data-reveal] { transition-delay: var(--delay, 0ms); }

  /* Masks sit on an INNER element (the artwork frame, or .ink inside a
     heading). IntersectionObserver treats an element hidden by its own
     clip-path as invisible, so the observed element itself is never clipped. */
  .motion [data-reveal^="wipe"] .work__frame {
    clip-path: inset(0 0 0 0);
    transition: clip-path 950ms var(--ease-print) var(--delay, 0ms), transform 220ms var(--ease-out);
  }
  .motion [data-reveal="wipe-up"]:not(.is-in) .work__frame    { clip-path: inset(100% 0 0 0); }
  .motion [data-reveal="wipe-down"]:not(.is-in) .work__frame  { clip-path: inset(0 0 100% 0); }
  .motion [data-reveal="wipe-left"]:not(.is-in) .work__frame  { clip-path: inset(0 0 0 100%); }
  .motion [data-reveal="wipe-right"]:not(.is-in) .work__frame { clip-path: inset(0 100% 0 0); }

  .motion [data-reveal="ink"] > .ink {
    display: block;
    clip-path: inset(-12% -4% -12% -4%);
    transition: clip-path 1100ms var(--ease-print) var(--delay, 0ms);
  }
  .motion [data-reveal="ink"]:not(.is-in) > .ink { clip-path: inset(0 100% 0 0); }

  .motion [data-reveal="rise"] {
    transition: opacity 600ms var(--ease-out), transform 750ms var(--ease-out);
    transition-delay: var(--delay, 0ms);
  }
  .motion [data-reveal="rise"]:not(.is-in) { opacity: 0; transform: translateY(18px); }

  .motion [data-reveal="deal"] {
    transition: opacity 450ms var(--ease-out), transform 850ms var(--ease-out);
    transition-delay: var(--delay, 0ms);
  }
  .motion [data-reveal="deal"]:not(.is-in) { opacity: 0; transform: translateY(56px) rotate(-3deg); }
  .motion [data-reveal="deal"]:nth-child(even):not(.is-in) { transform: translateY(64px) rotate(2.5deg); }

  /* Portrait: a red panel slides off to the right, the photo settles */
  .motion [data-reveal="unmask"]::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--red);
    transform-origin: 100% 50%;
    transition: transform 900ms var(--ease-in-out);
    transition-delay: var(--delay, 0ms);
    pointer-events: none;
  }
  .motion [data-reveal="unmask"].is-in::after { transform: scaleX(0); }
  .motion [data-reveal="unmask"] img { transition: transform 1300ms var(--ease-out); transition-delay: var(--delay, 0ms); }
  .motion [data-reveal="unmask"]:not(.is-in) img { transform: scale(1.08); }

  /* Opening load sequence (plays once, never blocks: links work immediately) */
  .motion .poster__title { animation: ink-down 650ms var(--ease-print) both; }
  .motion .opening__plate .work__frame { animation: plate-in 1050ms 260ms var(--ease-print) both; }
  .motion .opening__intro { animation: rise-in 480ms 140ms var(--ease-out) backwards; }
  .motion .page-title__ink { animation: ink-across 1100ms var(--ease-print) both; }
  .motion .page-head__intro { animation: rise-in 700ms 300ms var(--ease-out) both; }

  /* Viewer opening: a quick settle; no motion on close */
  .viewer[open] { animation: viewer-in 220ms var(--ease-out); }
  .viewer[open] .viewer__img { animation: viewer-img 260ms var(--ease-out); }
}

@media (prefers-reduced-motion: no-preference) {
  /* Smooth only for jumps within a page. main.js adds .smooth-scroll after
     load, so arriving from another page at #artist jumps straight there. */
  html.motion.smooth-scroll { scroll-behavior: smooth; }

  /* Artwork settles inside its frame while the mask opens; the caption follows */
  .motion [data-reveal^="wipe"] .work__img { transition: transform 1200ms var(--ease-out); transition-delay: var(--delay, 0ms); }
  .motion [data-reveal^="wipe"]:not(.is-in) .work__img { transform: scale(1.08); }
  @media (max-width: 599px) {
    .motion [data-reveal^="wipe"] .work__frame { transition-duration: 650ms, 220ms; }
    .motion [data-reveal^="wipe"]:not(.is-in) .work__img { transform: none; }
  }
  .motion [data-reveal^="wipe"] .caption,
  .motion [data-reveal="deal"] .caption {
    transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out);
    transition-delay: calc(var(--delay, 0ms) + 260ms);
  }
  .motion [data-reveal^="wipe"]:not(.is-in) .caption,
  .motion [data-reveal="deal"]:not(.is-in) .caption { opacity: 0; transform: translateY(8px); }

  /* Artists page portrait opens from a vertical slit inside its mat (Home uses "unmask") */
  .motion [data-reveal="slit"] img,
  .motion [data-reveal="slit"] .portrait__empty {
    clip-path: inset(0 0 0 0);
    transition: clip-path 1000ms var(--ease-print) var(--delay, 0ms), transform 1300ms var(--ease-out) var(--delay, 0ms);
  }
  .motion [data-reveal="slit"]:not(.is-in) img,
  .motion [data-reveal="slit"]:not(.is-in) .portrait__empty { clip-path: inset(0 47% 0 47%); transform: scale(1.12); }

  /* Phones and tablets: the poster holds still while the red "Selected work"
     sheet slides over it. Native sticky, no scroll scripting. */
  @media (max-width: 959px), (max-height: 599px) {
    .motion .stack .opening {
      position: sticky;
      top: var(--stick-top, 0px);
      z-index: 0;
    }
    .motion .stack .selected {
      position: relative;
      z-index: 1;
      background-color: var(--paper);
      background-image: var(--grain-paper);
      border-top: 2px solid var(--ink);
    }
  }

  /* While the red enquiry panel is on screen, the header's identical
     button steps aside so the same call to action never shows twice */
  .header-cta { transition: clip-path 240ms var(--ease-out), visibility 0s linear 0s, background-color 160ms ease, transform 140ms var(--ease-out); }

  /* Artist menu: a name gives way slightly under a pointer press (Enter on a
     focused name jumps without a dip). The first and last names give way
     from their own side, as the viewer's words do, so they stay on the
     page's text edges. */
  .motion .jumpnav a { transition: transform 160ms var(--ease-out); }
  .motion .jumpnav a:active:not(:focus-visible) { transform: scale(0.97); }
  .motion .jumpnav li:first-child a { transform-origin: left center; }
  .motion .jumpnav li:last-child a { transform-origin: right center; }

  /* A phone press moves only the name: the full cell stays tappable.
     Individual scale composes with the Deep Lens transform. */
  @media (max-width: 47.99em) {
    .motion .jumpnav a { transition: none; }
    .motion .jumpnav a:active:not(:focus-visible) { transform: none; }
    .motion .jumpnav__name { transition: scale 160ms var(--ease-out); }
    .motion .jumpnav a:active:not(:focus-visible) .jumpnav__name { scale: 0.97; }
  }

  /* Deep Lens: the names turn away from the centre, where they grow 15%.
     Each untransformed li supplies its own inline view timeline. Native
     scroll progress drives the labels directly; unsupported browsers keep
     the same readable, flat snap row. */
  @supports (view-timeline: --artist-wheel inline) and (animation-timeline: --artist-wheel) {
    @media (max-width: 47.99em) {
      .motion .jumpnav li { view-timeline: --artist-wheel inline; }
      .motion .jumpnav__name { animation: jumpnav-deep-lens linear both; animation-timeline: --artist-wheel; }
    }
  }
}
@keyframes jumpnav-deep-lens {
  0% {
    transform: perspective(360px) translateZ(-26px) rotateY(-70deg) scale(.76);
  }
  15% {
    transform: perspective(360px) translateZ(-22px) rotateY(-62deg) scale(.8);
  }
  25% {
    transform: perspective(360px) translateZ(-16px) rotateY(-46deg) scale(.86);
  }
  32% {
    transform: perspective(360px) translateZ(-12px) rotateY(-40deg) scale(.9);
  }
  40% {
    transform: perspective(360px) translateZ(-5px) rotateY(-24deg) scale(1);
  }
  50% {
    transform: perspective(360px) translateZ(0) rotateY(0deg) scale(1.15);
  }
  60% {
    transform: perspective(360px) translateZ(-5px) rotateY(24deg) scale(1);
  }
  68% {
    transform: perspective(360px) translateZ(-12px) rotateY(40deg) scale(.9);
  }
  75% {
    transform: perspective(360px) translateZ(-16px) rotateY(46deg) scale(.86);
  }
  85% {
    transform: perspective(360px) translateZ(-22px) rotateY(62deg) scale(.8);
  }
  100% {
    transform: perspective(360px) translateZ(-26px) rotateY(70deg) scale(.76);
  }
}

@media (min-width: 720px) {
  .enquiry-visible .header-cta {
    clip-path: inset(0 0 0 100%);
    visibility: hidden;
    transition: clip-path 240ms var(--ease-out), visibility 0s linear 240ms;
  }
}

@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  .site-header { view-transition-name: site-header; }
  .motion::view-transition-old(root) { animation: vt-out 200ms var(--ease-out) both; }
  .motion::view-transition-new(root) { animation: vt-in 520ms var(--ease-print) both; }
}
html:not(.motion)::view-transition-group(*),
html:not(.motion)::view-transition-old(*),
html:not(.motion)::view-transition-new(*) { animation: none; }
/* Pointer opening settles as one sheet. Keyboard opening is immediate;
   there is no item stagger and the icon switches state without a delay. */
@media (max-width: 719px) and (prefers-reduced-motion: no-preference) {
  .motion .menu-toggle__label {
    transform-origin: right center;
    transition: transform 140ms var(--ease-out);
  }
  .motion .menu-toggle:active:not(:focus-visible) .menu-toggle__label { transform: scale(0.97); }
  .motion.pointer-menu .menu-sheet:not([hidden]) {
    animation: mobile-menu-appear 180ms cubic-bezier(.22, 1, .36, 1);
  }
}
@keyframes mobile-menu-appear {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes vt-out { to { opacity: 0.4; } }
@keyframes vt-in { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes ink-down   { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(-12% -12% -12% -12%); } }
@keyframes ink-across { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(-12% -12% -12% -12%); } }
@keyframes plate-in   { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes rise-in    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes viewer-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes viewer-img { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: none; } }

/* Scroll scenes write transforms inline; hint the compositor only there */
.motion .poster__line,
.motion .opening__plate,
.motion .opening__flood,
.motion .flashpre__item .work { will-change: transform; }

/* 12. REDUCED MOTION + SAFETY ------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Everything is already static here (html.motion is never set). This is a
     safety net. Use "none", not a 1ms duration: a duration alone would make
     every property, including font size, transition. */
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
}
/* Windows forced colours drop the paper tab, the ink rule and the text shadow
   that mark the current page, so draw an outline and a heavy underline instead. */
@media (forced-colors: active) {
  .site-nav a[aria-current="page"] { border: 2px solid CanvasText; border-bottom: 0; }
  /* the artist menu's rail is a shadow, which forced colours remove: draw it
     as a border in the same place, below the menu */
  .jumpnav { box-sizing: content-box; border-bottom: 2px solid CanvasText; }
}

/* Keep the menu and wheel legible in the reader's system colours. */
@media (forced-colors: active) and (max-width: 719px) {
  .menu-sheet {
    --focus: Highlight;
    --focus-halo: Canvas;
    background: Canvas;
    color: CanvasText;
    border-top-color: CanvasText;
  }
  .menu-sheet__label { color: CanvasText; }
  .menu-sheet__pages a[aria-current="page"] { text-shadow: none; text-decoration: underline; }
  .menu-sheet a { color: LinkText; }
  .menu-sheet__artists,
  .menu-toggle::before { border-color: CanvasText; }
  .menu-sheet a:focus-visible,
  .menu-toggle:focus-visible { outline-color: Highlight; }
}
@media (forced-colors: active) and (max-width: 47.99em) {
  .jumpnav { background: Canvas; }
  .jumpnav::after { border-top-color: Highlight; }
  .jumpnav a:focus-visible .jumpnav__name { outline-color: Highlight; }
}
