/* ===========================================================================
   Opal Web Services
   ---------------------------------------------------------------------------
   The page has no colour of its own. Ivory and ink are the whole brand; every
   hue that appears is borrowed from whichever client's work is on screen and
   published as --live and --live-ink. When nothing is live it falls back to
   ink, which is the argument the company is making, stated in CSS.
   ========================================================================= */

:root {
  --sc-canvas:     #F6F2EA;
  --sc-surface:    #FFFCF6;
  --sc-ink:        #16130F;
  --sc-ink-soft:   #5C5649;
  --sc-accent:     #16130F;
  --sc-accent-ink: #FFFCF6;

  --sunk:          #E7E1D4;

  --sc-font-display: "Bricolage Grotesque", "Archivo", system-ui, sans-serif;
  --sc-font-text:    "Geist", system-ui, sans-serif;

  /* shadows tinted to the canvas hue, never black on a warm ground */
  --sc-shadow-color: 38 24% 22%;
  --sc-edge: inset 0 1px 0 rgb(255 255 255 / 0.7);

  /* the borrowed pair. Set live by site.js, reset to ink. */
  --live:     #16130F;
  --live-ink: #16130F;

  /* the stone: two large corners, two small, held everywhere on the page.
     This is the mark's own silhouette used as the frame for every client. */
  --stone-a: clamp(20px, 3.2vw, 52px);
  --stone-b: clamp(7px, 1.1vw, 16px);
  --stone:   var(--stone-a) var(--stone-b) var(--stone-a) var(--stone-b);
  --stone-sm: clamp(10px, 1.4vw, 20px) clamp(4px, 0.5vw, 7px)
              clamp(10px, 1.4vw, 20px) clamp(4px, 0.5vw, 7px);
}

.sc-grain { opacity: 0.03; }

::selection { background: color-mix(in oklab, var(--live) 26%, transparent); }

/* one focus ring for the page, in whatever colour is live */
:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--live-ink);
  outline-offset: 3px;
  border-radius: 3px;
}

.skip {
  position: fixed; top: -100px; left: var(--sc-gutter); z-index: 200;
  background: var(--sc-ink); color: var(--sc-surface);
  padding: var(--sc-3) var(--sc-5); border-radius: var(--sc-r-sm);
  text-decoration: none;
}
.skip:focus { top: var(--sc-4); }

/* ───────────────────────────────────────────────────────────── chrome ── */

.chrome {
  position: fixed; inset: 0 0 auto 0; z-index: var(--sc-z-chrome);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sc-5);
  padding: clamp(0.85rem, 1.6vw, 1.6rem) var(--sc-gutter);
  pointer-events: none;
}
/* The chrome floats with no bar under it, which was fine while every act
   carried a screen of padding. Tightened up, body copy now travels under the
   mark and the band constantly. A soft wash, fading out well before it could
   read as an edge, keeps both legible without becoming the bar the grammar
   refuses. */
.chrome::before {
  content: ""; position: absolute; inset: -0.5rem 0 auto 0; height: 190%;
  z-index: -1; pointer-events: none;
  background: linear-gradient(to bottom,
    rgb(246 242 234 / 0.97) 0%,
    rgb(246 242 234 / 0.9) 42%,
    rgb(246 242 234 / 0.55) 68%,
    rgb(246 242 234 / 0) 100%);
}
.chrome > * { pointer-events: auto; }

.mark {
  display: inline-flex; align-items: center; gap: var(--sc-3);
  color: var(--sc-ink); text-decoration: none;
}
.mark__stone { width: clamp(24px, 2.4vw, 32px); height: auto; overflow: visible; }
.mark__fire {
  stroke: var(--live);
  transition: stroke 480ms var(--sc-ease-out);
}
.mark__word {
  font-family: var(--sc-font-display);
  font-size: var(--sc-t-base);
  font-weight: 600;
  letter-spacing: var(--sc-track-snug);
  line-height: 1;
  display: flex; flex-direction: column; gap: 2px;
}
.mark__sub {
  font-family: var(--sc-font-text);
  font-size: 0.6rem; font-weight: 400;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--sc-ink-soft);
}

/* The band. Seven stones, grey until you have passed the work they stand
   for, then that client's colour for the rest of the page. It is a record of
   what you have looked at, not a progress bar and not a section list. */
.band { display: flex; align-items: center; gap: clamp(5px, 0.7vw, 10px); }
.band__stone {
  position: relative;
  width: clamp(16px, 1.9vw, 26px); height: clamp(11px, 1.3vw, 17px);
  border-radius: var(--stone-sm);
  background: var(--sunk);
  box-shadow: var(--sc-edge);
  text-decoration: none;
  transition: background 520ms var(--sc-ease-out), transform 160ms var(--sc-ease-out);
}
.band__stone.is-seen { background: var(--hue, var(--sunk)); }
.band__stone.is-live { transform: translateY(-2px) scale(1.14); }
.band__stone > span {
  position: absolute; right: 0; top: calc(100% + 8px);
  font-size: var(--sc-t-xs); letter-spacing: 0.02em;
  color: var(--sc-ink); background: var(--sc-surface);
  padding: 3px 8px; border-radius: 4px; box-shadow: var(--sc-e1);
  white-space: nowrap; opacity: 0; transform: translateY(-3px);
  transition: opacity 140ms var(--sc-ease-out), transform 140ms var(--sc-ease-out);
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .band__stone:hover { transform: translateY(-2px) scale(1.14); }
  .band__stone:hover > span { opacity: 1; transform: none; }
}
.band__stone:focus-visible > span { opacity: 1; transform: none; }

/* ─────────────────────────────────────────────────── the stone frame ── */

/* ONE rounded, clipping box per piece of media, and the media itself paints
   nothing of its own. Two nested boxes carrying the same radius disagree by a
   fraction of a pixel at the curve, and the inner one's --sunk ground shows
   through as a grey wedge outside each corner. */
.cell, .work__frame, .day__frame {
  border-radius: var(--stone);
  overflow: hidden;
  background: var(--sunk);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--sc-ink) 9%, transparent);
}
video.clip { width: 100%; height: auto; object-fit: cover; display: block; background: none; }
.cell video.clip { position: absolute; inset: 0; height: 100%; }
.tile .work__frame video.clip { position: absolute; inset: 0; height: 100%; }
/* The wipe rides a wrapper, never the rounded box: clip-path has no round
   term here and would square the corners off for the length of the reveal. */
.work__wipe { display: block; }

/* ─────────────────────────────────────────────────── 1 · the wall ── */

.wall {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4.5rem);
  padding: clamp(6rem, 11vh, 9rem) var(--sc-gutter) clamp(2rem, 6vh, 4rem);
}
.wall__say { max-width: 34ch; }
.wall__say h1 { max-width: 26ch; font-size: clamp(2.05rem, 2.9vw, 3.45rem); }
.wall__say .sc-lede { margin-top: var(--sc-5); color: var(--sc-ink-soft); }
.cta--hero { margin-top: clamp(1.25rem, 3vh, 2rem); }
.tm { font-size: 0.52em; vertical-align: super; letter-spacing: 0; opacity: 0.8; }

/* Aligned on arrival. --recede is read off --sc-p, which the engine
   publishes on the act, and is the only thing that moves the tray. */
.wall__tray {
  --recede: clamp(0, calc((var(--sc-p, 0) - 0.62) * 2.7), 1);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: clamp(0.45rem, 0.85vw, 0.9rem);
  height: clamp(20rem, 62svh, 40rem);
  transform: scale(calc(1 - 0.06 * var(--recede)));
  transition: transform 60ms linear;
}
.tile {
  position: relative;
  margin: 0;
  opacity: calc(1 - 0.22 * var(--recede));
  will-change: opacity;
}
.tile .work__frame {
  height: 100%;
  box-shadow: var(--sc-e2), var(--sc-edge),
              inset 0 0 0 1px color-mix(in oklab, var(--sc-ink) 9%, transparent);
}
/* A square's name and line exist for the close-up only. At rest the wall is
   seven moving sites and nothing else, which is what makes it the hook. */
.tile > figcaption {
  position: absolute; left: 0; top: calc(100% + 0.75rem);
  width: max(100%, 22rem);
  opacity: 0; pointer-events: none;
  transition: opacity 260ms var(--sc-ease-out);
}
.tile.is-focused > figcaption {
  opacity: 1;
  background: color-mix(in oklab, var(--sc-surface) 94%, transparent);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  padding: clamp(0.6rem, 1.4vh, 0.9rem) clamp(0.7rem, 1.6vw, 1rem);
  border-radius: var(--stone-sm);
  box-shadow: var(--sc-e2);
}
/* Nine, in a four-by-three board: six squares and three doubles fill it
   exactly, so no cell is ever left blank. */
.tile--1 { grid-area: 1 / 1; }
.tile--2 { grid-area: 1 / 2; }
.tile--3 { grid-area: 1 / 3 / 2 / 5; }
.tile--4 { grid-area: 2 / 1 / 3 / 3; }
.tile--5 { grid-area: 2 / 3; }
.tile--6 { grid-area: 2 / 4; }
.tile--7 { grid-area: 3 / 1; }
.tile--8 { grid-area: 3 / 2; }
.tile--9 { grid-area: 3 / 3 / 4 / 5; }

/* ────────────────────────────────────────── the portfolio, as categories ──
   Four trades, one format. Every category is the same diptych: two frames one
   gutter apart under a named rule. What stops four identical rows from reading
   as a template is that each pair is hung on a different tilt, and each one is
   brought in by a different device (a wipe, the pointer, differential travel,
   a held frame). The air lives between the categories, never between a pair. */

.act--cat { padding-block: clamp(1.1rem, 2.6vh, 2.25rem); }
.act--cat:first-of-type { padding-top: clamp(2.5rem, 5.5vh, 4.5rem); }

.cat {
  font-family: var(--sc-font-display);
  font-size: var(--sc-t-lg);
  font-weight: 600;
  letter-spacing: 0.02em;
  margin: 0 0 clamp(0.7rem, 1.6vh, 1.15rem);
  display: flex; align-items: center; gap: var(--sc-4);
  color: var(--sc-ink);
}
.cat::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--sc-hairline);
}

.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.3vw, 1.4rem);
  align-items: start;
}

/* The tilt. Static geometry, not motion: it survives reduced-motion because
   nothing about it animates. Rotation rides the figure and never the frame,
   so it cannot collide with the parallax or tilt device inside it. */
.pair > .work:nth-child(1) { transform: translateY(var(--y1, 0)) rotate(var(--r1, 0deg)); }
.pair > .work:nth-child(2) { transform: translateY(var(--y2, 0)) rotate(var(--r2, 0deg)); }
.pair--a { --y1: 0;                        --r1: -0.75deg; --y2: clamp(0.9rem, 2.6vw, 2.2rem); --r2: 0.5deg; }
.pair--b { --y1: clamp(0.9rem, 2.6vw, 2.2rem); --r1: 0.65deg;  --y2: 0;                        --r2: -0.8deg; }
.pair--c { --y1: 0;                        --r1: 0.55deg;  --y2: clamp(1.1rem, 3vw, 2.6rem);  --r2: -0.7deg; }
.pair--d { --y1: clamp(0.5rem, 1.6vw, 1.4rem); --r1: -0.55deg; --y2: 0;                        --r2: 0.6deg; }
.pair--e { --y1: 0;                        --r1: 0.5deg;   --y2: clamp(0.8rem, 2.2vw, 1.9rem); --r2: -0.6deg; }
.pair--f { --y1: clamp(0.7rem, 2vw, 1.7rem);   --r1: 0.45deg;  --y2: 0;                        --r2: -0.7deg; }
.pair--g { --y1: 0;                        --r1: -0.6deg;  --y2: clamp(0.9rem, 2.4vw, 2rem);  --r2: 0.45deg; }
/* Three in a row rather than two. One category has three names in it, and
   splitting it in half would say they are two different trades. */
.pair > .work:nth-child(1) { grid-column: 1; }
.pair > .work:nth-child(2) { grid-column: 2; }
.pair--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pair--three > .work:nth-child(3) { grid-column: 3; }
.pair--three > .work:nth-child(3) {
  transform: translateY(clamp(0.5rem, 1.5vw, 1.3rem)) rotate(0.6deg);
}
.pair--three .work__frame video { aspect-ratio: 16 / 9.6; }

.work { margin: 0; perspective: 1100px; }
/* Every preview answers the pointer the same way. The tilt itself is the
   engine's; what is here is the lift that goes with it. */
.work__frame { transition: box-shadow 220ms var(--sc-ease-out); }
@media (hover: hover) and (pointer: fine) {
  .work__frame:hover { box-shadow: var(--sc-e3), inset 0 0 0 1px color-mix(in oklab, var(--sc-ink) 9%, transparent); }
}
.work figcaption { margin-top: clamp(0.55rem, 1.2vh, 0.9rem); }
.work h3 {
  font-family: var(--sc-font-display);
  font-size: var(--sc-t-lg);
  letter-spacing: var(--sc-track-snug);
  line-height: 1.1;
  margin: 0;
  color: var(--own, var(--sc-ink));
}
.work figcaption p {
  margin: var(--sc-2) 0 0;
  color: var(--sc-ink-soft);
  font-size: var(--sc-t-sm);
  max-width: 46ch;
}
.work__frame video { aspect-ratio: 16 / 8.6; }
.work__frame { box-shadow: var(--sc-e2), inset 0 0 0 1px color-mix(in oklab, var(--sc-ink) 9%, transparent); }

/* ──────────────────────────────────────────────── 5 · one day ── */

/* The one category with a single name in it. Rather than shrink to half a row
   like the paired categories, the frame takes the width two frames would have
   had, and the writing goes underneath it in two columns. A half-width clip
   floating in a whole pinned viewport read as a gap, not as a held beat. */
.day { display: grid; align-content: center; }
.day .pair--e { grid-template-columns: minmax(0, 1fr); }
.day .work--solo .work__frame video { aspect-ratio: 16 / 7.5; }
.day .work--solo figcaption {
  display: grid;
  grid-template-columns: minmax(0, 0.3fr) minmax(0, 0.7fr);
  gap: clamp(1rem, 3vw, 3rem);
  align-items: baseline;
  margin-top: clamp(0.7rem, 1.6vh, 1.15rem);
}
.day .work--solo figcaption h3 { font-size: var(--sc-t-xl); }
.day .work--solo figcaption p { max-width: 68ch; font-size: var(--sc-t-sm); }
.day .cat { margin-bottom: clamp(0.7rem, 1.6vh, 1.15rem); }
/* The floor is 0.82, not lower: ink at 0.82 on this ground still measures
   over 4.5:1, and anything dimmer trades legibility for an effect. */
.day figcaption {
  --arrive: clamp(0, calc(var(--sc-p, 0) * 3.2), 1);
  opacity: calc(0.82 + 0.18 * var(--arrive));
  transform: translateY(calc((1 - var(--arrive)) * 9px));
}

/* ─────────────────────────────────────────────── 6 · four lines ── */

/* a flow section straight after a pinned act already inherits a whole
   viewport of un-pinning before its own padding starts */
.act--plain { padding-block-start: clamp(2rem, 5vh, 4.5rem); }
.plain { max-width: 56rem; }
.plain__line {
  font-family: var(--sc-font-display);
  font-size: var(--sc-t-xl);
  line-height: 1.22;
  letter-spacing: var(--sc-track-snug);
  margin: 0;
  padding-block: clamp(1.1rem, 2.6vh, 2rem);
  text-wrap: balance;
}
.plain__line + .plain__line { border-top: 1px solid var(--sc-hairline); }

/* ─────────────────────────────────────── 7 · the loupe, and the well ── */

.loupe {
  display: grid; justify-items: center;
  grid-template-rows: auto minmax(0, 1fr) auto;
  align-content: stretch;
  gap: clamp(0.8rem, 2vh, 1.6rem);
  padding: clamp(4.5rem, 10vh, 7rem) var(--sc-gutter) clamp(2.5rem, 6vh, 4rem);
}
.loupe__hint {
  margin: 0; font-size: var(--sc-t-sm); letter-spacing: 0.02em;
  color: var(--sc-ink-soft);
}

.sheet {
  position: relative;
  width: min(72rem, 100%);
  align-self: center;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-auto-rows: auto;
  gap: clamp(0.6rem, 1.1vw, 1.1rem);
}
.cell {
  position: relative; margin: 0; padding: 0; border: 0;
  min-height: 0; min-width: 0;
  background: var(--sunk);
  box-shadow: var(--sc-e1), var(--sc-edge);
  cursor: pointer;
  /* the sheet is dead until a hand crosses it */
  filter: grayscale(1) contrast(0.88);
  opacity: 0.66;
  transition: filter 420ms var(--sc-ease-out), opacity 420ms var(--sc-ease-out),
              transform 320ms var(--sc-ease-out), box-shadow 320ms var(--sc-ease-out);
}
.cell.is-lit {
  filter: none; opacity: 1;
  transform: scale(1.035);
  box-shadow: var(--sc-e3), var(--sc-edge);
  z-index: 2;
}
.cell__name {
  color: var(--own, var(--sc-ink));
  position: absolute; left: 0; bottom: 0; z-index: 3;
  font-size: var(--sc-t-xs); letter-spacing: 0.1em; text-transform: uppercase;
  background: var(--sc-surface);
  padding: 5px 10px; border-radius: 0 10px 0 0;
  opacity: 0; transform: translateY(4px);
  transition: opacity 240ms var(--sc-ease-out), transform 240ms var(--sc-ease-out);
}
.cell.is-lit .cell__name { opacity: 1; transform: none; }

/* the eighth stone. A well, not a tile. */
.cell:not(.cell--empty) { aspect-ratio: 16 / 10; }
/* Eleven does not divide by six, so the last one takes two columns rather
   than leaving a hole in the sheet. */
.cell[data-cell="fernwake"] { grid-column: span 2; aspect-ratio: 32 / 10; }
.cell--empty {
  grid-column: 1 / 7; grid-row: 3;
  min-height: clamp(9rem, 22svh, 13rem);
  filter: none; opacity: 1; cursor: default;
  background: var(--sunk);
  box-shadow: inset 0 3px 10px hsl(var(--sc-shadow-color) / 0.22),
              inset 0 -1px 0 rgb(255 255 255 / 0.45);
  display: grid; align-content: center;
  overflow: hidden;
  padding: clamp(1rem, 2.2vw, 2rem);
}
.cell--empty::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: center / clamp(44px, 4.4vw, 70px) no-repeat
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 34'><path d='M11 2h13a8 8 0 0 1 8 8v13a8 8 0 0 1-8 8H11a8 8 0 0 1-8-8V10a8 8 0 0 1 8-8z' fill='none' stroke='%2316130F' stroke-width='1.2'/><path d='M8.5 23.5C10.5 14 15.5 9.5 25 8' fill='none' stroke='%2316130F' stroke-width='1.6' stroke-linecap='round'/></svg>");
  opacity: calc(0.34 - 0.34 * clamp(0, calc((var(--sc-p, 0) - 0.54) * 8), 1));
}
.vacancy__in { max-width: 44ch; }
.cell--empty h2 { margin: 0; font-size: clamp(1.5rem, 2.1vw, 2.15rem); }
.cell--empty p {
  margin: var(--sc-3) 0 var(--sc-4);
  color: var(--sc-ink-soft); font-size: var(--sc-t-sm); max-width: 38ch;
}
.cta {
  display: inline-block;
  background: var(--sc-ink); color: var(--sc-surface);
  text-decoration: none;
  font-weight: 500; letter-spacing: 0.01em;
  padding: 0.75rem 1.5rem;
  border-radius: var(--stone-sm);
  box-shadow: var(--sc-e2);
  transition: background 160ms var(--sc-ease-out), box-shadow 160ms var(--sc-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .cta:hover { background: var(--live-ink); box-shadow: var(--sc-e3); }
}
.cta:active { transform: translateY(1px); }

/* the loupe itself: a soft disc of the live colour that clears the sheet */
.lens {
  position: absolute; z-index: 1;
  width: clamp(200px, 22vw, 320px); aspect-ratio: 1;
  border-radius: 50%;
  left: 0; top: 0;
  translate: calc(var(--lx, 50vw) - 50%) calc(var(--ly, 50vh) - 50%);
  background: radial-gradient(circle at 50% 42%,
    color-mix(in oklab, var(--live) 20%, transparent) 0%,
    color-mix(in oklab, var(--live) 7%, transparent) 46%,
    transparent 70%);
  border: 1px solid color-mix(in oklab, var(--live-ink) 34%, transparent);
  box-shadow: 0 10px 40px -12px color-mix(in oklab, var(--live-ink) 40%, transparent);
  pointer-events: none;
  opacity: 0;
  transition: opacity 400ms var(--sc-ease-out), border-color 480ms var(--sc-ease-out);
  mix-blend-mode: multiply;
}
.loupe.is-hunting .lens { opacity: 1; }

.foot {
  width: min(72rem, 100%);
  display: flex; justify-content: space-between; gap: var(--sc-5);
  flex-wrap: wrap;
  padding-top: clamp(0.8rem, 2vh, 1.4rem);
  border-top: 1px solid var(--sc-hairline);
  font-size: var(--sc-t-sm); color: #433E32;
  position: relative; z-index: 4;
}
.foot__mark { color: var(--sc-ink); letter-spacing: 0.02em; }
.foot__concept {
  flex: 1 0 100%;
  margin: var(--sc-2) 0 0;
  font-size: var(--sc-t-xs);
  color: var(--sc-ink-soft);
}

/* ─────────────────────────────────────────────────────── reduced ── */

@media (prefers-reduced-motion: reduce) {
  .tile { opacity: 1 !important; }
  .wall__tray { transform: none !important; }
  .day__frame { transform: none !important; }
  /* the lens is the peak's whole mechanism; without motion the sheet simply
     arrives already awake rather than becoming unreachable */
  .cell { filter: none; opacity: 1; }
  .cell__name { opacity: 1; transform: none; }
  .lens { display: none; }
}

/* ──────────────────────────────────────────────────────── mobile ── */

@media (max-width: 1000px) {
  .day .work--solo figcaption { grid-template-columns: minmax(0, 1fr); gap: var(--sc-2); }
}

@media (max-width: 860px) {
  .wall {
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: clamp(1.2rem, 3vh, 2rem);
    padding: clamp(5rem, 13vh, 7rem) var(--sc-gutter) clamp(1.5rem, 4vh, 3rem);
  }
  .wall__say h1 { font-size: var(--sc-t-2xl); max-width: none; }
  .wall__say .sc-lede { font-size: var(--sc-t-base); margin-top: var(--sc-3); }
  .wall__tray {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    height: clamp(15rem, 40svh, 24rem);
    margin-right: 0;
  }

  /* two clips fewer on a phone: five decoders instead of seven, and both of
     the hidden ones get a full act of their own later on the page */
  /* five clips on a phone instead of nine */
  .tile--3, .tile--6, .tile--8, .tile--9 { display: none; }
  .tile > figcaption { display: none; }
  .tile--1 { grid-area: 1 / 1; }
  .tile--2 { grid-area: 1 / 2; }
  .tile--5 { grid-area: 2 / 1; }
  .tile--7 { grid-area: 2 / 2; }
  .tile--4 { grid-area: 3 / 1 / 4 / 3; }

  /* On a phone there is no pointer to hunt with, so the sheet stops being a
     sheet: the seven stones share one frame and the page itself turns them
     over as you scroll. No scroll region nested inside a pinned stage. */
  .sheet { display: block; position: relative; height: auto; }
  .sheet .cell:not(.cell--empty) {
    position: absolute; inset: 0 0 auto 0;
    height: clamp(13rem, 42svh, 21rem);
    opacity: 0; filter: none; transform: none;
    transition: opacity 420ms var(--sc-ease-out);
  }
  .sheet .cell.is-lit { opacity: 1; transform: none; box-shadow: var(--sc-e2), var(--sc-edge); }
  .cell--empty {
    grid-column: auto; grid-row: auto;
    margin-top: calc(clamp(13rem, 42svh, 21rem) + 0.9rem);
  }
  .loupe { grid-template-rows: auto auto auto; align-content: start; }
  .sheet { height: auto; max-height: none; }
  .pair, .pair--three { grid-template-columns: minmax(0, 1fr); gap: clamp(1rem, 4vw, 1.6rem); }
  .pair--three > .work:nth-child(3) { transform: rotate(0.6deg); }
  .pair > .work:nth-child(1),
  .pair > .work:nth-child(2) { transform: rotate(var(--r1, 0deg)); }
  .pair > .work:nth-child(2) { transform: rotate(var(--r2, 0deg)); }
  .act--cat { padding-block: clamp(1.25rem, 3vh, 2rem); }
  .plain__line { font-size: var(--sc-t-lg); }
}

@media (max-width: 560px) {
  .mark__word { font-size: var(--sc-t-sm); }
  .band { gap: 5px; }
}

/* ───────────────────────────────────────────── click to look closer ──
   Any preview can be opened. The rest of the page goes behind frosted
   ivory, and the one you opened comes forward with its name and its line
   grown to match. Nothing is moved in the DOM: the figure keeps its place
   in the grid and is lifted out of the stack, so no layout jumps and no
   clip goes on playing behind the veil. */

.veil {
  position: fixed; inset: 0; z-index: 100;
  background: color-mix(in oklab, var(--sc-canvas) 58%, transparent);
  backdrop-filter: blur(18px) saturate(0.86);
  -webkit-backdrop-filter: blur(18px) saturate(0.86);
  opacity: 0; pointer-events: none;
  transition: opacity 340ms var(--sc-ease-out);
  cursor: zoom-out;
}
body.has-focus .veil { opacity: 1; pointer-events: auto; }

.work__frame { cursor: zoom-in; }
body.has-focus .work__frame { cursor: default; }

/* Every preview opens at one size, whatever size it sits at in the page. A
   jewellery frame is a third of a row and a restaurant frame is a half, and
   scaling them in place opened them at a third and a half of the screen. They
   all come out to the same centred box instead.

   !important is load-bearing here: .pair > .work:nth-child(n) carries the tilt
   as a transform at a higher specificity than any class pair, and the tilt has
   to be off while the frame is centred. */
.work.is-focused {
  position: fixed !important;
  left: 50%; top: 50%;
  width: min(60rem, 76vw);
  height: auto;
  margin: 0 !important;
  transform: translate(-50%, -52%) !important;
  z-index: 121;
}
.work.is-focused .work__frame { height: auto; max-height: 68svh; }
.work.is-focused .work__frame video {
  position: static;
  width: 100%; height: auto;
  max-height: 68svh;
  aspect-ratio: auto;                 /* the clip's own shape, not the grid's */
  object-fit: cover;
}
.work.is-focused .work__frame {
  box-shadow: 0 8px 20px hsl(var(--sc-shadow-color) / 0.22),
              0 34px 80px -14px hsl(var(--sc-shadow-color) / 0.42),
              inset 0 0 0 1px color-mix(in oklab, var(--own, var(--sc-ink)) 38%, transparent);
  cursor: zoom-out;
}
/* the name and the line grow with it, and the name takes its own colour at
   full strength rather than the dimmed body tone */
.work.is-focused figcaption { margin-top: clamp(0.7rem, 1.5vh, 1.1rem); }
.work.is-focused h3 { font-size: var(--sc-t-xl); color: var(--own, var(--sc-ink)); }
.work.is-focused figcaption p { font-size: var(--sc-t-base); color: var(--sc-ink); max-width: 52ch; }
.work.is-focused h3, .work.is-focused figcaption p {
  transition: font-size 300ms var(--sc-ease-out), color 300ms var(--sc-ease-out);
}

.focus-hint {
  position: fixed; z-index: 121;
  left: 50%; bottom: clamp(1rem, 4vh, 2.5rem); translate: -50% 0;
  font-size: var(--sc-t-xs); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--sc-ink-soft);
  background: color-mix(in oklab, var(--sc-surface) 86%, transparent);
  padding: 0.5rem 0.9rem; border-radius: var(--sc-r-pill);
  box-shadow: var(--sc-e1);
  opacity: 0; pointer-events: none;
  transition: opacity 260ms var(--sc-ease-out);
}
body.has-focus .focus-hint { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .work.is-focused { transform: none; }
  .day figcaption { transform: none; }
}

@media (max-width: 860px) {
  .work.is-focused h3 { font-size: var(--sc-t-lg); }
}

/* A pinned stage is its own stacking context and clips its contents, so a
   focused preview inside one cannot reach above the veil on its own. Lift the
   stage with it. The stage paints no ground, so the frost still shows through
   behind the figure rather than being hidden by it. */
[data-sc-stage].is-lifted { z-index: 120; overflow: visible; }
[data-sc-stage].is-lifted .work.is-focused { z-index: 121; }
/* Lifting the stage carries its other previews up with it, past the veil, so
   the frost has to be applied to them directly or the close-up opens over a
   wall that is still perfectly sharp. */
[data-sc-stage].is-lifted .work:not(.is-focused),
[data-sc-stage].is-lifted .wall__say {
  filter: blur(16px) saturate(0.84);
  opacity: 0.55;
}
[data-sc-stage].is-lifted .work:not(.is-focused),
[data-sc-stage].is-lifted .wall__say {
  transition: filter 340ms var(--sc-ease-out), opacity 340ms var(--sc-ease-out);
}


/* ─────────────────────────── a hero square, opened ──
   At rest a square is a cell in the board and nothing else. Opened, it stops
   being a cell and presents exactly the way a card on the features page does:
   a full-size frame with the name and the line set directly underneath it.
   Every square carries an explicit grid-area, so taking one out of flow
   leaves its own cell empty and moves none of the others. */

[data-sc-stage].is-lifted .wall__tray { transform: none; }

/* the floating label a square uses in the board is not needed once the frame
   has room under it, so the caption goes back to being an ordinary caption */
.tile.is-focused > figcaption {
  position: static;
  width: auto;
  margin-top: clamp(0.7rem, 1.5vh, 1.1rem);
  background: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  padding: 0;
  border-radius: 0;
  box-shadow: none;
  opacity: 1;
}

@media (max-width: 860px) {
  .work.is-focused { width: 90vw; }
  .work.is-focused .work__frame, .work.is-focused .work__frame video { max-height: 52svh; }
}
