/* ---------------------------------------------------------------------------
   Daniel Wilson . Works
   Static site. Tokens first, then components.
   --------------------------------------------------------------------------- */

:root {
  /* Palette: Cold Press. Cool stone ground, scarlet, cool near-black. */
  --paper:        #E3E6E4;
  --paper-raised: #EDEFEC;
  --ink:          #14161A;
  --ink-deep:     #070809;

  /* One red, three lightnesses off hue 356deg. --accent is the brand red and
     is used for fills and large text; at 3.64:1 it cannot carry small text, so
     --accent-ink (4.73:1 on --paper) does that, and --accent-lift (4.64:1 on
     --ink) does it on dark surfaces. */
  --accent:       #EB0919;
  --accent-ink:   #C90815;

  --rule:         2px solid var(--ink);
  --hairline:     1px solid rgba(20, 22, 26, 0.25);

  --lift-sm:      6px 6px 0 rgba(20, 22, 26, 0.14);
  --lift-card:    6px 6px 0 rgba(20, 22, 26, 0.10);
  --lift-lg:      8px 8px 0 rgba(20, 22, 26, 0.20);

  --gap:          14px;
  --pad-panel:    clamp(20px, 3vw, 46px);

  --sans:         Rubik, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display:      "Hamburg Hand", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Warm greys stepped off --ink; both clear 4.5:1 on the new ground. */
  --ink-muted:    #4B4F54;
  --ink-faint:    #5A5E63;

  --accent-lift:  #F72C3A;

  --ease:         cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- fonts ---------------------------------------------------------------- */

/* Rubik, self-hosted. It is a variable font, so one file serves 400 and 700 -
   the weight range below tells the browser it can use it for both. The two
   subsets carry Google's own unicode-ranges, so latin-ext is only fetched if a
   page actually needs those characters. SIL Open Font License. */
@font-face {
  font-family: "Rubik";
  src: url("../assets/Rubik-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Rubik";
  src: url("../assets/Rubik-latin-ext.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Hamburg Hand";
  src: url("../assets/HamburgHand-Light.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Hamburg Hand";
  src: url("../assets/HamburgHand-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Hamburg Hand";
  src: url("../assets/HamburgHand-Bold.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

/* --- base ----------------------------------------------------------------- */

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

/* Component classes below set `display`, which would otherwise out-rank the
   UA rule for [hidden]. Keep the attribute authoritative. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: var(--gap);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  font-synthesis: none;
}

main {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

img, video { display: block; max-width: 100%; }

a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--accent-ink); }

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

/* Browser surfaces theming — selection, caret, focus, scrollbar. */
::selection { background: var(--ink); color: var(--paper); }
:root { caret-color: var(--accent); accent-color: var(--accent); scrollbar-color: var(--ink) var(--paper); }

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

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  z-index: 200;
}
.skip:focus { left: var(--gap); top: var(--gap); color: var(--paper); }

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

.link {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--accent-ink);
  text-decoration: underline;
  cursor: pointer;
}

/* --- masthead ------------------------------------------------------------- */

/* The bar is the only thing that sticks — roughly 56px, not a third of the
   viewport. It sits in a zero-height wrapper so it can't add layout gap. */
.bar {
  position: sticky;
  top: var(--gap);
  z-index: 50;
}
.bar__inner {
  background: var(--paper);
  border: var(--rule);
  padding: 10px clamp(12px, 1.6vw, 18px);
  box-shadow: var(--lift-sm);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 12px;
}

.masthead {
  background: var(--paper);
  border: var(--rule);
  padding: clamp(16px, 2vw, 26px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: var(--lift-sm);
}

.wordmark {
  justify-self: start;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  border-bottom: var(--rule);
  padding-bottom: 4px;
  display: inline-flex;
  overflow: hidden;
}
.wordmark__gap { display: inline-block; width: 0; transition: width 0.28s var(--ease); }
.wordmark__suffix {
  display: inline-block;
  margin-left: 0;
  transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), margin-left 0.28s var(--ease);
}
.wordmark[data-phase="on"] .wordmark__gap { width: 6px; }
.wordmark[data-phase="on"] .wordmark__suffix { margin-left: 6px; }
.wordmark[data-hidden="true"] .wordmark__suffix { opacity: 0; transform: translateY(-6px); }

.detail {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 10px;
  border: var(--rule);
  padding: 7px 12px;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.detail__label { font-size: 9px; letter-spacing: 0.2em; }
.detail__end { font-size: 9px; letter-spacing: 0.16em; color: var(--ink-muted); }
/* A native range ignores thumb and track styling unless appearance is reset,
   so the control is drawn from scratch. --fill is set by app.js on input; it
   paints the portion left of the thumb, which WebKit has no pseudo-element for
   (Firefox uses ::-moz-range-progress instead). */
.detail input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 80px;
  height: 18px;
  margin: 0;
  background: none;
  cursor: pointer;
}

.detail input[type="range"]::-webkit-slider-runnable-track {
  height: 14px;
  box-sizing: border-box;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: linear-gradient(to right,
    var(--accent) 0 var(--fill, 50%), var(--paper) var(--fill, 50%) 100%);
}
.detail input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 18px;
  height: 18px;
  /* Centred against the track's content box (14px box - 4px borders = 10px),
     which is what WebKit offsets the thumb from: (10 - 18) / 2. */
  margin-top: -4px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--ink);
  cursor: pointer;
}

.detail input[type="range"]::-moz-range-track {
  height: 14px;
  box-sizing: border-box;
  border: 2px solid var(--ink);
  border-radius: 999px;
  background: var(--paper);
}
.detail input[type="range"]::-moz-range-progress {
  height: 14px;
  box-sizing: border-box;
  border: 2px solid var(--ink);
  border-right: 0;
  border-radius: 999px 0 0 999px;
  background: var(--accent);
}
.detail input[type="range"]::-moz-range-thumb {
  box-sizing: border-box;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--ink);
  cursor: pointer;
}

.masthead__h1 {
  font-size: clamp(22px, 2.6vw, 40px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  font-weight: 400;
  text-wrap: balance;
}
.masthead__mark { color: var(--accent-ink); border-bottom: 6px solid var(--accent); }
/* The continuation starts on its own line. It is empty at L0, and an empty
   block has no height, so nothing is reserved when it is not shown. */
.masthead__lede-more { display: block; }
.masthead__lede {
  font-size: clamp(13.5px, 1vw, 17px);
  line-height: 1.55;
  /* Long for a body measure, but this is a one-to-two line lede sitting under
     a full-width h1 — breaking it at 72ch left it wrapping for no reason. */
  /* Was capped at 118ch, which left ~300px of the container unused and
     stranded the final words on a line of their own. */
  max-width: min(150ch, 1560px);
  text-wrap: balance;
  color: var(--ink-muted);
}
.masthead__note {
  align-self: flex-end;
  text-align: right;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-ink);
  border-bottom: 2px solid var(--accent-ink);
  padding-bottom: 2px;
}

/* --- hero ----------------------------------------------------------------- */

/* Aspect ratios chosen against the source video's own 16:9, so `cover` crops
   as little as possible. Mobile keeps a little height (4:3) because a true
   16:9 band is too thin to read as a banner at 375px. */
.hero {
  position: relative;
  border: var(--rule);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  max-height: 72vh;
  display: flex;
  box-shadow: var(--lift-lg);
  background: var(--ink-deep);
}
@media (min-width: 560px)  { .hero { aspect-ratio: 3 / 2; } }
@media (min-width: 900px)  { .hero { aspect-ratio: 16 / 9; } }
@media (min-width: 1600px) { .hero { aspect-ratio: 21 / 9; } }
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,22,26,0.55) 0%, rgba(20,22,26,0) 30%);
}
.hero__badge {
  position: relative;
  z-index: 2;
  margin: clamp(20px, 2.4vw, 36px);
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 2px solid var(--paper);
  color: var(--paper);
  padding: 5px 10px;
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.hero__dot { width: 6px; height: 6px; background: var(--accent); border-radius: 50%; }

/* --- tabs ----------------------------------------------------------------- */

.tabs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.tab {
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
  padding: clamp(12px, 1.5vw, 18px) clamp(12px, 1.6vw, 20px);
  border: var(--rule);
  cursor: pointer;
  font-family: var(--display);
  text-transform: uppercase;
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--lift-sm);
  transition: background 0.18s, color 0.18s, translate 0.18s, box-shadow 0.18s;
}
.tab:hover { translate: 0 -2px; }
.tab[aria-expanded="true"] {
  background: var(--ink);
  color: var(--paper);
  box-shadow: 6px 6px 0 var(--accent);
}
.tab__num { font-size: 10px; letter-spacing: 0.24em; color: var(--ink-faint); }
.tab[aria-expanded="true"] .tab__num { color: rgba(227,230,228,0.70); }
/* Tracking tuned so all four labels hold one line from ~1100px up. */
.tab__title { font-size: clamp(12px, 1.08vw, 17px); letter-spacing: 0.03em; text-wrap: balance; }
.tab__sign { font-size: 18px; line-height: 1; margin-left: auto; }

/* --- panel ---------------------------------------------------------------- */

.panel {
  border: var(--rule);
  background: var(--paper-raised);
  padding: var(--pad-panel);
  position: relative;
}
.panel[hidden] { display: none; }

.panel__close {
  position: absolute;
  top: 14px; right: 14px;
  width: 34px; height: 34px;
  border: var(--rule);
  background: var(--paper);
  font-family: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  z-index: 3;
}
.panel__close:hover { background: var(--ink); color: var(--paper); }

.panel__head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border-bottom: var(--rule);
  padding-bottom: 12px;
  margin-bottom: clamp(18px, 2.4vw, 30px);
  padding-right: 48px;
}
.panel__count {
  font-size: 11px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
/* Column, not a wrapping row. Side-by-side only held for the shortest lead;
   the other three overflowed onto their own flex line, so one section read
   differently from the rest. Stacking makes all four consistent and closes the
   gap the wrap was opening under the heading. */
.panel__titles {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.panel__h2 {
  font-size: clamp(28px, 4.2vw, 62px);
  line-height: 0.9;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  font-weight: 400;
}
/* 60ch forced a needless second line inside a container half as wide again.
   These are one-line leads, not body copy, so the measure can run longer. */
.panel__lead {
  font-size: 18px;
  line-height: 1.35;
  color: var(--ink-muted);
  max-width: min(105ch, 100%);
  text-wrap: pretty;
}

/* --- grids ---------------------------------------------------------------- */

/* Pure CSS. The old JS picked the largest divisor of the item count, which
   collapsed any prime count (11, 13, 17 projects) to a single column. */
.grid { display: grid; gap: var(--gap); grid-template-columns: 1fr; }

/* Variable counts: fill the row, cap the card width. */
.grid--fluid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.grid--talks { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }

/* Fixed six: 1 / 2 / 3 all divide evenly, so rows are never left ragged.
   Capped so cards don't stretch to an unreadable measure on a wide monitor. */
.grid--six { max-width: 1680px; margin-inline: auto; }
@media (min-width: 620px)  { .grid--six { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .grid--six { grid-template-columns: repeat(3, 1fr); } }
.grid__empty { padding: 24px 0; color: var(--ink-muted); font-size: 14px; }

/* --- quotes (problems) ---------------------------------------------------- */

/* Cards stretch to their row's tallest, so a short quote left a big gap above
   the closing mark. Centring the text keeps every card evenly spaced between
   its two marks regardless of how long the quote runs. */
.quote {
  border: var(--rule);
  background: var(--paper);
  padding: clamp(18px, 1.9vw, 26px);
  box-shadow: var(--lift-card);
  position: relative;
  display: flex;
  align-items: center;
}
/* Both marks sit 14px in from their corner. The offsets differ because the
   glyph ink is not centred in its line box: measured at 34px, the ink starts
   8px below the box top and ends 26px above its bottom, so identical top and
   bottom values look uneven (6px against 24px). Each is set from the ink:
   14-8=6, and 14-26=-12. */
.quote::before,
.quote::after {
  font-size: 34px;
  color: var(--ink-faint);
  position: absolute;
}
.quote::before { content: "\201C"; top: 6px; left: 18px; }
.quote::after  { content: "\201D"; bottom: -12px; right: 18px; }
.quote p {
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.5;
}

/* --- ways to work --------------------------------------------------------- */

.way {
  border: var(--rule);
  background: var(--ink);
  color: var(--paper);
  padding: clamp(18px, 1.9vw, 26px);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.way__title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: clamp(15px, 1.3vw, 21px);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.way__num { font-size: 10px; letter-spacing: 0.2em; color: rgba(227,230,228,0.70); }
.way p { font-size: 13.5px; line-height: 1.55; color: rgba(227,230,228,0.84); }

.freebie {
  margin-top: 22px;
  padding: 16px 18px;
  border: 2px dashed var(--ink);
  font-size: 14px;
  line-height: 1.55;
}
.freebie strong { text-transform: uppercase; letter-spacing: 0.1em; }

/* --- filters -------------------------------------------------------------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  padding: 10px 12px;
  border: var(--rule);
  margin-bottom: 10px;
}
.filters:last-of-type { margin-bottom: 18px; }
.filters__label {
  font-size: 9.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-right: 6px;
}
.filters__clear {
  font-family: var(--display);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: none;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
  color: var(--accent-ink);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0;
  font-family: var(--display);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 9px;
  cursor: pointer;
  border: 1.5px solid rgba(20, 22, 26, 0.45);
  background: var(--paper);
  color: var(--ink);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.pill--dot { gap: 5px; }
.pill__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--pill-color); }
.pill:hover { border-color: var(--pill-color); }
.pill[aria-pressed="true"] {
  background: var(--pill-color);
  border-color: var(--pill-color);
  color: var(--ink);
}
.pill[aria-pressed="true"] .pill__dot { background: var(--ink); }

/* --- work cards ----------------------------------------------------------- */

.work {
  border: var(--rule);
  background: var(--paper);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.work__title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  border-bottom: var(--hairline);
  padding-bottom: 10px;
  font-size: 16px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.2;
}
.work__num { font-size: 10px; letter-spacing: 0.2em; color: var(--ink-faint); }
/* Justified on request. hyphens:auto matters here - without it, justifying a
   ~300px column opens rivers of white space between words. */
.work__text {
  font-size: 13.5px;
  line-height: 1.55;
  text-align: justify;
  hyphens: auto;
}
.work__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 0;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
  border: 1.5px solid var(--tag-color);
}
.tag--dot { gap: 5px; border-color: rgba(20, 22, 26, 0.4); }
.tag__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--tag-color); }

/* --- talks ---------------------------------------------------------------- */

.talk {
  position: relative;
  border: var(--rule);
  background: var(--ink);
  color: var(--paper);
  display: flex;
  flex-direction: column;
  padding: 0;
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: translate 0.2s, box-shadow 0.2s;
}
.talk:hover { translate: 0 -3px; box-shadow: var(--lift-card); }
/* --media-bg is set per card from the image's own flat backdrop, so a logo
   letterboxed in a landscape window sits on matching colour instead of black
   bars. Photographs have no flat backdrop and fall back to --ink-deep. */
.talk__media {
  display: block;
  height: 180px;
  overflow: hidden;
  background: var(--media-bg, var(--ink-deep));
  border-bottom: var(--rule);
}
.talk__media img { width: 100%; height: 100%; }
.talk__body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
/* Titles run to one or two lines depending on length; reserving two keeps
   every card in the grid the same height. */
.talk__title {
  font-size: 15px;
  line-height: 1.25;
  min-height: 2.5em;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-wrap: balance;
}
/* Now carries "Venue · Category", so the wide tracking that suited a single
   word costs too much width; the longest venue ran to three lines and left the
   card heights ragged. min-height reserves two lines so every card matches
   whether its venue wraps or not. */
.talk__cat {
  margin-top: auto;
  font-size: 10px;
  letter-spacing: 0.06em;
  line-height: 1.4;
  min-height: 2.8em;
  text-transform: uppercase;
  color: var(--accent-lift);
}
.talk__plus {
  position: absolute;
  bottom: 12px; right: 12px;
  width: 30px; height: 30px;
  border: 2px solid var(--paper);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  background: var(--ink);
}

/* --- lightbox ------------------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(20, 22, 26, 0.88);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
}
.lightbox[hidden] { display: none; }
.lightbox__sheet {
  background: var(--paper);
  border: var(--rule);
  max-width: 1600px;
  width: 100%;
  max-height: 92vh;
  overflow: auto;
  display: flex;
  flex-wrap: wrap;
  position: relative;
}
.lightbox__close {
  position: absolute;
  top: 12px; right: 12px;
  width: 34px; height: 34px;
  border: var(--rule);
  background: var(--paper);
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  z-index: 2;
}
.lightbox__close:hover { background: var(--ink); color: var(--paper); }
.lightbox__media {
  flex: 1 1 640px;
  min-width: min(400px, 100%);
  height: 640px;
  background: var(--ink);
}
.lightbox__media img { width: 100%; height: 100%; object-fit: cover; }
.lightbox__media img[data-fit="contain"] { object-fit: contain; }
.lightbox__body {
  flex: 1 1 640px;
  min-width: min(400px, 100%);
  padding: clamp(30px, 3.6vw, 60px);
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.lightbox__cat {
  font-size: 14px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-ink);
}
.lightbox__title {
  font-size: clamp(30px, 3.4vw, 52px);
  line-height: 1.05;
  text-transform: uppercase;
  font-weight: 400;
  text-wrap: balance;
}
.lightbox__desc { font-size: 18px; line-height: 1.6; max-width: 60ch; }
.lightbox__nav { display: flex; gap: 10px; margin-top: auto; padding-top: 14px; }
.lightbox__arrow {
  width: 64px; height: 64px;
  border: var(--rule);
  background: var(--paper);
  font-family: inherit;
  font-size: 24px;
  cursor: pointer;
}
.lightbox__arrow:hover { background: var(--ink); color: var(--paper); }

/* --- contact -------------------------------------------------------------- */

.contact {
  border: var(--rule);
  background: var(--paper);
  padding: clamp(18px, 2.6vw, 34px);
  display: grid;
  --contact-col: 400px;
  grid-template-columns: 1fr 1fr 1fr;
  gap: clamp(18px, 3vw, 40px);
  /* The buttons column is the only one sized by its content, so it sets the
     row height. The two image columns stretch to match and fit their artwork
     inside, which is what keeps all three the same height without either
     image dragging the footer taller. */
  align-items: stretch;
  margin-top: auto;
  box-shadow: var(--lift-lg);
}
/* Both image columns carry an intrinsic ratio, so their height tracks column
   width — and since all three columns now share one height, either could drag
   the footer to 900px+ on a wide monitor. Capping both at the same width keeps
   the footer sane; below ~1400px the columns are narrower than the cap and
   nothing changes. */
.contact__logo {
  width: 100%;
  max-width: var(--contact-col);
  margin-inline: auto;
  /* No ratio and no in-flow child: the tile takes whatever height the buttons
     column sets. Anything with an intrinsic size in here would drive the row
     instead, which is what kept dragging the footer taller. */
  position: relative;
  height: 100%;
  min-height: 0;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: var(--rule);
}
/* 3% inset. The logo is a landscape mark in a narrow column, so once the tile
   matches the buttons' height there is always some red above and below — the
   floor is ~26% even at zero padding. 3% keeps it at ~31%, split evenly, which
   reads as deliberate padding rather than a gap. */
.contact__logo img {
  position: absolute;
  inset: 3%;
  width: 94%;
  height: 94%;
  object-fit: contain;
}
/* object-fit keeps the portrait proportional inside whatever box it is given,
   and its flat ground is --paper, so the spare space is invisible. height:100%
   is needed because the width/height attributes (kept to reserve space against
   layout shift) apply as presentational hints and would otherwise pin it. */
/* Same trick: the portrait is taken out of flow so its 954x1080 ratio cannot
   size the row. It fills whatever box it is given and contains within it, and
   its flat ground is --paper, so the spare width either side is invisible. */
.contact__portrait {
  position: relative;
  height: 100%;
  min-height: 0;
}
.contact__portrait img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.contact__actions {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 12px;
}

.cta {
  position: relative;
  font-family: var(--display);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--paper);
  color: var(--ink);
  border: var(--rule);
  padding: clamp(18px, 2.2vw, 28px);
  /* One expression fixes the height of all three buttons, so the two-line
     email button matches its single-line neighbours instead of being short.
     The +4px is the 2px border on each edge. */
  min-height: calc(2 * clamp(18px, 2.2vw, 28px) + clamp(14px, 1.5vw, 23px) * 1.3 + 4px);
  font-size: clamp(14px, 1.5vw, 23px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  box-shadow: var(--lift-lg);
  transition: box-shadow 0.18s, translate 0.18s, background 0.18s, color 0.18s;
}
.cta:hover { box-shadow: 3px 3px 0 rgba(20,22,26,0.2); translate: 5px 5px; background: var(--ink); color: var(--paper); }
.cta--solid { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.cta--solid:hover { box-shadow: 3px 3px 0 rgba(20,22,26,0.2); translate: 5px 5px; background: var(--ink); color: var(--paper); }

/* Only one button should read as primary at a time. The solid button is black
   by default, so hovering a sibling used to leave two black buttons at once —
   it now steps back to paper, and the black always marks whatever the pointer
   (or keyboard focus) is actually on. */
.contact__actions:hover .cta--solid:not(:hover),
.contact__actions:focus-within .cta--solid:not(:focus-visible) {
  background: var(--paper);
  color: var(--ink);
}
/* Taken out of flow and pinned to the same inset as the button's padding.
   In flow the label and arrow were centred as one group, so a longer label
   pushed its arrow further right - an 8px spread across the three. */
.cta__arrow {
  position: absolute;
  right: clamp(18px, 2.2vw, 28px);
  top: 50%;
  translate: 0 -50%;
  font-size: 1.1em;
  line-height: 1;
}

/* The email button carries the address under its label. The two live in their
   own flex column — setting `display:block` on them alone would do nothing,
   since as flex children of .cta they would still lay out in a row. Padding is
   trimmed so the extra line does not make this button taller than its
   neighbours. */
.cta--stack { padding-block: 8px; }
.cta__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}
.cta__sub {
  font-family: var(--sans);
  font-size: clamp(10px, 0.85vw, 13px);
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--ink-muted);
}
.cta--stack:hover .cta__sub { color: inherit; }

/* All three badge files are now identical 512x512 squares cropped to their
   artwork, so one fixed box sizes them consistently. */
.badges {
  --badge: clamp(44px, 4.4vw, 62px);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  margin-top: 8px;
}
.badges img {
  width: var(--badge);
  height: var(--badge);
  object-fit: contain;
  flex: 0 0 auto;
}

/* This badge's hexagon is narrower than the other two (90.4% of its box against
   100% and 97.9%), so matched heights read as a smaller mark. 512/463 = 1.106. */
.badges__wide { width: calc(var(--badge) * 1.1) !important; height: calc(var(--badge) * 1.1) !important; }

.colophon {
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 6px 0 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* The statutory company line: an address in wide uppercase tracking is hard
   work to read, so it drops the caps and tightens up. */
.colophon__company {
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 10.5px;
  text-wrap: balance;
}

/* --- responsive ----------------------------------------------------------- */

@media (max-width: 960px) {
  .tabs { grid-template-columns: repeat(2, 1fr); }
  .contact { grid-template-columns: 1fr; }
  .contact__logo { max-width: 260px; margin-inline: auto; }
  .contact__logo { height: auto; aspect-ratio: 27 / 20; }
  .contact__portrait {
    position: static;
    max-width: 320px;
    margin-inline: auto;
    height: auto;
    aspect-ratio: 954 / 1080;
  }
  .contact__portrait img { position: static; }
  .lightbox__media { height: 360px; }
}

@media (max-width: 680px) {
  :root { --gap: 10px; }
  .bar__inner { grid-template-columns: 1fr; gap: 8px; justify-items: start; }
  .detail { width: 100%; justify-content: space-between; }
  .tabs { grid-template-columns: 1fr; }
  .lightbox { padding: 10px; }
  .lightbox__media { height: 240px; }
  .lightbox__body { padding: 20px; gap: 14px; }
  .lightbox__arrow { width: 52px; height: 52px; }
  .panel__lead { font-size: 15px; }
  .panel { padding: 18px 16px; }
  .panel__head { padding-right: 44px; }
  .masthead__note { text-align: left; align-self: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* The video stays visible and shows its poster frame; JS just won't play it.
     Hiding it here left an empty box for anyone with reduced motion on. */
}
