/* SALIKA theme. Shared by index.html and portfolio.html.
   scrollcraft.css is the engine floor; this is the brand on top of it.

   The page is a book: warm paper, black ink, and photographs printed onto it
   as plates. Everything that is not a photograph is paper. The vermilion is a
   seal, not a button; it marks and it never fills. */

html { scrollbar-gutter: stable; }   /* no width jump when the page is locked */

:root {
  /* paper, and the ink that goes on it. --lai-paper is the constant: the
     engine rewrites --sc-canvas as the page drifts between paper and plate,
     so anything that must stay paper on a dark plate reads from here. */
  --lai-paper:     #E9E3D6;
  /* what sits behind the fixed chrome. Paper by default, plate wherever a
     photograph is under the chrome: never --sc-canvas, which the engine only
     catches up on once an act is part-way through. */
  --lai-chrome-bg: #E9E3D6;
  --sc-canvas:     #E9E3D6;
  --sc-surface:    #DED6C5;
  --sc-ink:        #16130F;
  --sc-ink-soft:   #6A6255;
  --sc-accent:     #A6371F;   /* oxidised vermilion. a chop mark, not a CTA */
  --sc-accent-ink: #F6F2E9;

  /* the plate: where a photograph is printed, the page goes dark so the
     photograph is the only light in the spread */
  --lai-plate:     #12100D;
  --lai-plate-ink: #EFE9DC;
  /* the constants. Tokens above drift with the page; these never move, so any
     subtree that must stay on one ground can restate itself from here. */
  --lai-ink:          #16130F;
  --lai-ink-soft:     #6A6255;
  --lai-accent:       #A6371F;
  --lai-plate-soft:   #9C9385;
  --lai-plate-surface:#1B1815;
  /* one hue, two lightnesses. The paper stop is unreadable on plate (2.8:1),
     which is what a page that hard-cuts between grounds has to carry. */
  --lai-accent-plate: #E0623F;

  --sc-font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --sc-font-text:    "Instrument Sans", system-ui, sans-serif;
  --sc-font-mono:    ui-monospace, "SF Mono", Menlo, monospace;

  /* square catalogue, not an app */
  --sc-r-sm: 0; --sc-r-md: 0; --sc-r-lg: 0; --sc-r-pill: 0;

  /* shadows on paper are short and warm, never blue */
  --sc-shadow-color: 30 30% 8%;

  /* how far down the fixed chrome column reaches */
  --lai-chrome: 15.5rem;

  /* signature move: the centre of the inked band, and its half-height */
  --lai-line: 58vh;
  --lai-band: 15vh;
  --lai-feather: 17vh;
}

body { background: var(--sc-canvas); color: var(--sc-ink); }

/* the engine has no screen-reader utility, and the catalogue numerals are
   decorative overlays, so the real number is spoken from here */
.sc-sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* the grain is paper tooth here, so it is warmer and slightly stronger */
.sc-grain { opacity: .07; mix-blend-mode: multiply; }

/* ------------------------------------------------------------- chrome -- */
.chrome-scrim {
  position: fixed; inset: 0 0 auto 0;
  height: calc(var(--lai-chrome) + var(--sc-6));
  z-index: calc(var(--sc-z-chrome) - 1); pointer-events: none;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--lai-chrome-bg) 90%, transparent) 0%,
    color-mix(in srgb, var(--lai-chrome-bg) 66%, transparent) 40%,
    color-mix(in srgb, var(--lai-chrome-bg) 26%, transparent) 74%,
    transparent 100%);
}
.chrome {
  position: fixed; inset: 0 0 auto 0; z-index: var(--sc-z-chrome);
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: var(--sc-5) var(--sc-gutter);
  pointer-events: none;
}
.chrome > * { pointer-events: auto; }

/* over a full-bleed plate the page is black, so the chrome takes plate ink.
   The flag is set from the drifted canvas colour, in the page, not the engine. */
[data-plate="dark"] { --lai-chrome-bg: var(--lai-plate); }
[data-plate="dark"] .mark a,
[data-plate="dark"] .index a[aria-current="true"],
[data-plate="dark"] .index .book,
[data-plate="dark"] .lang button[aria-pressed="true"] { color: var(--lai-plate-ink); }
[data-plate="dark"] .mark small,
[data-plate="dark"] .index a,
[data-plate="dark"] .lang button,
[data-plate="dark"] .lang span { color: color-mix(in srgb, var(--lai-plate-ink) 62%, transparent); }
[data-plate="dark"] .mark__rule { background: var(--lai-plate-ink); }
@media (hover: hover) and (pointer: fine) {
  [data-plate="dark"] .index a:hover,
  [data-plate="dark"] .lang button:hover { color: var(--lai-plate-ink); }
}

/* ------------------------------------------------------------ the mark -- */
/* The studio's own calligraphic gesture, masked so it takes the page ink and
   inverts with it. The lockup around it is the evolution: the mark sits above
   a hand-weighted rule, the name is set wide underneath it in the book face,
   and the seal closes the group. Nothing here is a new logo; it is their mark
   given a typographic house. */
.mark { margin: 0; font-size: var(--sc-t-base); font-weight: 400; line-height: 1.1; }
/* The mark reads across, not down: stacked, the logo, the rule, the name and
   the line under it were four rows of chrome standing over the photographs.
   Side by side it is one row and roughly half the height, and the rule becomes
   the vertical join between the two halves. */
.mark a {
  color: var(--sc-ink); text-decoration: none;
  display: grid; align-items: center;
  grid-template-columns: auto auto auto;
  grid-template-areas:
    "logo rule name"
    "logo rule sub";
  row-gap: .18rem;
  column-gap: .7rem;
}
.mark__logo {
  grid-area: logo;
  width: clamp(3.6rem, 5vw, 4.8rem); aspect-ratio: 900 / 521;
  background: currentColor;
  -webkit-mask: url("assets/logo.png?v=938e89fd") left bottom / contain no-repeat;
  mask: url("assets/logo.png?v=938e89fd") left bottom / contain no-repeat;
}
.mark__rule {
  grid-area: rule;
  width: 1px; height: 2.1rem; background: var(--sc-ink); opacity: .4;
  /* still inked: lighter at the foot than the head */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 72%, rgba(0,0,0,.35) 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 72%, rgba(0,0,0,.35) 100%);
}
.mark__name {
  grid-area: name; align-self: end;
  font-family: var(--sc-font-display); font-size: var(--sc-t-base);
  letter-spacing: .2em; line-height: 1; text-indent: .2em;
}
.mark small {
  grid-area: sub; align-self: start;
  display: block;
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft); font-weight: 400;
}

/* the index of objects. gallery chrome: it jumps. */
.index { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.index a {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft); text-decoration: none;
  padding: 3px 0 3px 1.6rem; position: relative;
  transition: color 140ms var(--sc-ease-out);
}
.index a::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 1rem; height: 1px; background: currentColor; opacity: .45;
  transform-origin: 100% 50%; transform: scaleX(.4);
  transition: transform 160ms var(--sc-ease-out), opacity 160ms var(--sc-ease-out);
}
.index a[aria-current="true"] { color: var(--sc-ink); }
.index a[aria-current="true"]::before { transform: scaleX(1); opacity: 1; background: var(--sc-accent); }
@media (hover: hover) and (pointer: fine) { .index a:hover { color: var(--sc-ink); } }
.index .book { margin-top: var(--sc-3); color: var(--sc-ink); }
.index .book::before { background: var(--sc-accent); opacity: 1; }

/* ----------------------------------------------- signature move: the ink -- */
/* A fixed veil that drains everything to stencil except the band of screen you
   are reading through. On paper the drain runs the other way to the dark
   build: unread photographs go pale, like a transfer that has not been inked
   yet. No drawn line: the edge of the ink IS the line. The veil sits above the
   stages and below the copy, so type is never touched. */
.ink-veil {
  position: fixed; inset: 0; z-index: 2; pointer-events: none;
  backdrop-filter: grayscale(.92) contrast(.80) brightness(1.07);
  -webkit-backdrop-filter: grayscale(.92) contrast(.80) brightness(1.07);
  --a: calc(var(--lai-line) - var(--lai-band) - var(--lai-feather));
  --b: calc(var(--lai-line) - var(--lai-band));
  --c: calc(var(--lai-line) + var(--lai-band));
  --d: calc(var(--lai-line) + var(--lai-band) + var(--lai-feather));
  -webkit-mask-image: linear-gradient(to bottom, #000 var(--a), transparent var(--b), transparent var(--c), #000 var(--d));
  mask-image: linear-gradient(to bottom, #000 var(--a), transparent var(--b), transparent var(--c), #000 var(--d));
}
@supports not (backdrop-filter: grayscale(1)) { .ink-veil { display: none; } }
@media (prefers-reduced-motion: reduce) { .ink-veil { display: none; } }

/* ------------------------------------------------------------- objects -- */
/* A plate is a photograph printed full-bleed. The page behind it goes to
   plate-black so the photograph is the only light in the spread. */
.obj .plate { background: var(--lai-plate); }
.plate__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; max-width: none;
}
/* hero is art-directed: a landscape crop (face → needle on skin) for wide
   screens, a portrait crop for tall ones. Positions keep the needle in frame. */
.plate__img--hero { object-position: 50% 45%; }
@media (min-aspect-ratio: 21/9) { .plate__img--hero { object-position: 50% 62%; } }
@media (max-aspect-ratio: 1/1) { .plate__img--hero { object-position: 35% 50%; } }
.plate__img--peak { object-position: 50% 46%; }

/* the museum label. one schema, every object. It is a paper card laid on the
   photograph, not a translucent panel: the whole page is paper, so the label
   is the page showing through. */
.card {
  background: var(--lai-paper);
  padding: var(--sc-5) var(--sc-5) var(--sc-4);
  max-width: 26rem; color: var(--sc-ink);
  box-shadow: 0 14px 30px -18px hsl(var(--sc-shadow-color) / .55);
}
.card::after {
  /* the seal, bottom right of every label */
  content: ""; position: absolute; right: var(--sc-5); bottom: var(--sc-4);
  width: .5rem; height: .5rem; background: var(--sc-accent);
}
.card { position: relative; }
.card__no {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft); margin: 0 0 var(--sc-3);
  padding-bottom: var(--sc-3); border-bottom: 1px solid var(--sc-hairline-strong);
}
.card__title {
  font-family: var(--sc-font-display); font-size: var(--sc-t-xl);
  line-height: 1.06; letter-spacing: var(--sc-track-tight);
  margin: 0 0 var(--sc-4); color: var(--sc-ink); font-weight: 400;
  text-wrap: balance;
}
.spec { margin: 0; display: grid; grid-template-columns: 6.5rem 1fr; gap: 2px var(--sc-3); }
.spec dt {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft);
}
.spec dd { margin: 0; font-size: var(--sc-t-sm); color: var(--sc-ink); }
.spec dd .num { font-variant-numeric: tabular-nums; }

.card--anchor { position: absolute; z-index: var(--sc-z-copy); }
.card--bl { left: var(--sc-gutter); bottom: clamp(2rem, 9vh, 6rem); }
.card--tr { right: var(--sc-gutter); top: calc(var(--lai-chrome) + var(--sc-3)); }

/* --------------------------------------------------------------- paper -- */
.plate-sec { padding-block: var(--sc-section); }
.plate-sec--tight { padding-block: var(--sc-7) var(--sc-8); }
.eyebrow {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft); margin: 0;
}
.eyebrow--seal { display: flex; align-items: center; gap: .55rem; }
.eyebrow--seal::before { content: ""; width: .42rem; height: .42rem; background: var(--sc-accent); flex: 0 0 auto; }
.plate-h {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: var(--sc-t-2xl); line-height: 1.02;
  letter-spacing: var(--sc-track-tight); margin: 0; text-wrap: balance;
}
.note { font-size: var(--sc-t-sm); color: var(--sc-ink-soft); max-width: 42ch; margin: 0; line-height: 1.6; }

/* ----------------------------------------------------------- the rail -- */
/* Not a grid. The pieces are hung at three different sizes and three different
   heights, the way work is hung on a wall, and the numbers overlap the plates
   the way they do in a catalogue. */
.rail {
  display: flex; align-items: flex-end; gap: clamp(1.6rem, 2.6vw, 3rem);
  height: 100%; padding-inline: var(--sc-gutter);
  padding-block: calc(var(--lai-chrome) - 4.5rem) var(--sc-6);
  will-change: transform;
}
.rail__lead, .rail__end {
  flex: 0 0 auto; width: min(17rem, 74vw);
  display: flex; flex-direction: column; justify-content: flex-end; gap: var(--sc-4);
  padding-bottom: 2vh;
}
.piece { flex: 0 0 auto; width: clamp(13rem, 19vw, 16rem); position: relative; }
.piece figure { margin: 0 0 var(--sc-4); overflow: clip; background: var(--sc-surface); }
.piece img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
.piece .card__no {
  margin: 0 0 var(--sc-2); border: 0; padding: 0;
}
.piece h3 {
  font-family: var(--sc-font-display); font-weight: 400; font-size: var(--sc-t-lg);
  line-height: 1.06; letter-spacing: var(--sc-track-snug); margin: 0 0 var(--sc-3);
}
.piece .spec { grid-template-columns: 5.5rem 1fr; }
.piece .spec dd { font-size: var(--sc-t-xs); }

/* the hang. The plates are three heights and three widths, but every label
   sits on one baseline, so the wall reads as hung rather than scattered. The
   numeral is set in the margin above its own plate: over the photograph it
   fought the image and went pale under the stencil veil. */
.piece figure { height: 44vh; }
.piece img { height: 100%; aspect-ratio: auto; }
.piece--tall   { width: clamp(13rem, 18vw, 16rem); }
.piece--tall figure  { height: 52vh; }
.piece--short  { width: clamp(11rem, 15vw, 13rem); }
.piece--short figure { height: 33vh; }
.piece--wide   { width: clamp(15rem, 23vw, 20rem); }
.piece--wide figure  { height: 38vh; }
.piece--drop   { margin-top: clamp(1rem, 4vh, 3rem); }
.piece--rise   { margin-bottom: clamp(1rem, 4vh, 3rem); }

/* the catalogue numeral, in the margin above the plate */
.piece__n {
  display: block; margin: 0 0 .1rem; line-height: .82;
  font-family: var(--sc-font-display); font-size: clamp(2.2rem, 3.6vw, 3.2rem);
  color: var(--sc-ink); opacity: .3;
  font-variant-numeric: tabular-nums;
}

/* staggered settle, driven off the act's own progress */
@media (prefers-reduced-motion: no-preference) {
  .rail > * { --i: 0; }
  .rail > :not(:first-child) {
    opacity: clamp(.55, calc((var(--sc-p, 0) * 5) - (var(--i) * .55)), 1);
    transform: translate3d(0, calc((1 - clamp(0, calc((var(--sc-p, 0) * 5) - (var(--i) * .55)), 1)) * 14px), 0);
    transition: none;
  }
}

/* pinned stages hold one screen: they clear the chrome and centre what is
   left, so nothing is ever hidden behind the fixed column */
/* 100% here resolves against the SECTION, which is span x 100vh, so a 2.8-span
   act centred its content 140vh below the fold and the first third of the act
   was a blank screen. The stage is the viewport, not the act. */
.process-stage, .studio-stage {
  height: 100svh; display: grid; align-content: center;
  padding: var(--lai-chrome) 0 var(--sc-7);
  overflow: clip;
}
.studio-stage .maker__row { align-items: center; }
@media (min-width: 900px) { .studio-stage .maker__row { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); } }
.studio-stage .maker img { max-height: 52vh; aspect-ratio: 4 / 5; }
.studio-stage .maker { gap: var(--sc-6); }
.studio-stage .facts { padding-top: var(--sc-4); }

/* ---------------------------------------------------------- the process -- */
/* the draw is the act's own progress, so this needs no script at all */
#process { --draw: clamp(0, calc((var(--sc-p, 0) - 0.08) / 0.74), 1); }
/* Six steps, and one line that is drawn through them as you scroll. The line
   is the needle path: it is stencil ahead of you and ink behind you, which is
   the same rule the whole page runs on. Each step inks in as the line reaches
   it. */
.process { display: grid; gap: var(--sc-6); }
.process__head {
  display: grid; gap: var(--sc-5) var(--sc-8); align-items: end;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 900px) {
  .process__head { grid-template-columns: auto minmax(0, 15rem) minmax(0, 24rem); }
  .process__head .eyebrow { grid-column: 1 / -1; }
}
/* the macro of the needle entering skin. It is the one intimate frame on the
   page, and the process act is where it belongs: closer than a client ever
   sees it, next to the sentence explaining why it cannot be undone. */
.make--proc { margin: 0; overflow: clip; background: var(--sc-surface); }
.make--proc img { display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 5; max-height: 30vh; }
.process__track { position: relative; }
/* the line runs above the steps rather than through them: at full height it
   crossed the copy at its own troughs */
.process__line {
  position: absolute; left: 0; right: 0; top: 0;
  width: 100%; height: 4.5rem;
  overflow: visible; pointer-events: none;
}
.process__line path { fill: none; stroke-linecap: round; }
.process__line .stencil { stroke: var(--sc-ink); opacity: .17; stroke-width: 1.5; }
.process__line .inked {
  stroke: var(--sc-ink); stroke-width: 1.8;
  stroke-dasharray: var(--len, 1000);
  stroke-dashoffset: calc(var(--len, 1000) * (1 - var(--draw, 0)));
}
.process__steps {
  display: grid; gap: var(--sc-6) var(--sc-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding: 5.5rem 0 0; margin: 0; list-style: none;
}
@media (min-width: 900px) { .process__steps { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.step { display: grid; gap: var(--sc-2); align-content: start; }
.step__n {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); color: var(--sc-accent);
}
.step h3 {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: var(--sc-t-lg); line-height: 1.06; margin: 0;
  letter-spacing: var(--sc-track-snug);
}
.step p { margin: 0; font-size: var(--sc-t-xs); color: var(--sc-ink-soft); line-height: 1.6; }
/* stencil until the line arrives, then inked, and it holds. Each step owns a
   slice of the draw, so they land one at a time instead of together. */
@media (prefers-reduced-motion: no-preference) {
  .step { --at: calc(var(--s) + 1); }
}
.process__creed {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(1.8rem, 4.6vw, 3.4rem); line-height: 1.06;
  letter-spacing: var(--sc-track-tight); margin: 0; max-width: 20ch;
}
.process__creed em { font-style: italic; }

/* ------------------------------------------------------------ the rule -- */
.rule-sec { min-height: 54vh; display: grid; align-content: center; }
.rule-h {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(2.4rem, 7.2vw, 5.6rem); line-height: 1;
  letter-spacing: -0.025em; margin: 0; text-wrap: balance;
  max-width: 16ch;
}
.rule-h em { font-style: italic; color: var(--sc-accent); }

/* ----------------------------------------------------------- the healed -- */
/* Deliberately the opposite of the fresh work: the fresh pieces are printed
   full-bleed on plate-black, these are small plates with wide paper margins
   and a date under each one. Work that has settled gets shown quietly. */
.healed { display: grid; gap: var(--sc-6); }
.healed__head { display: grid; gap: var(--sc-4); max-width: 42rem; }
.healed__row {
  display: grid; gap: var(--sc-6) var(--sc-6);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 760px) { .healed__row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.healed figure { margin: 0; display: grid; gap: var(--sc-3); }
.healed img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 5; object-fit: cover; background: var(--sc-surface);
  max-height: 36vh;
}
.healed figcaption {
  display: grid; gap: 2px;
  padding-top: var(--sc-3); border-top: 1px solid var(--sc-hairline-strong);
}
.healed .h-no {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--sc-ink-soft);
}
.healed .h-age {
  font-family: var(--sc-font-display); font-size: var(--sc-t-lg); line-height: 1.1;
}
/* the second and third plate sit progressively lower, so the row reads as a
   hand laying prints down rather than a grid */
@media (min-width: 760px) {
  .healed__row > :nth-child(2) { margin-top: clamp(1rem, 3vh, 2.2rem); }
  .healed__row > :nth-child(3) { margin-top: clamp(2rem, 6vh, 4.4rem); }
}

/* ---------------------------------------------------------- the maker -- */
.maker { display: grid; gap: var(--sc-7); }
.maker__row { display: grid; gap: var(--sc-6) var(--sc-8); grid-template-columns: minmax(0, 1fr); align-items: end; }
@media (min-width: 900px) {
  .maker__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
}
.maker figure { margin: 0; }
.maker img { display: block; width: 100%; height: auto; aspect-ratio: 5 / 4; object-fit: cover; max-height: 38vh; }
.maker figure[data-sc-parallax] img { aspect-ratio: 4 / 5; }
.maker p { margin: 0; }
/* the practical facts run as one ruled band under the two rows */
.facts {
  display: grid; gap: var(--sc-4) var(--sc-6);
  grid-template-columns: minmax(0, 1fr);
  padding-top: var(--sc-5); border-top: 1px solid var(--sc-hairline-strong);
}
@media (min-width: 760px) { .facts { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.facts .spec { grid-template-columns: 5.5rem 1fr; }

/* ------------------------------------------------------------- inquiry -- */
.inquiry {
  height: 100%; display: grid; align-content: space-between;
  grid-template-rows: auto 1fr auto;
  /* only the form column has to clear the wordmark, which is one short row
     now. The contact column sits under the index and takes the rest of the
     clearance itself, so the act stops spending a third of the screen on
     padding it does not need. */
  padding: 7.5rem var(--sc-gutter) var(--sc-6);
  max-width: var(--sc-maxw); margin-inline: auto; width: 100%;
}
.inquiry__grid { display: grid; gap: var(--sc-7) var(--sc-8); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .inquiry__grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); } }
.ask { display: grid; gap: var(--sc-4); align-content: start; }

/* the form is a ledger, not an app. No boxes: each answer is written on a
   ruled line, the way it would be on a form in the studio. */
.ledger { display: grid; gap: var(--sc-5); margin: var(--sc-4) 0 0; }
.ledger__row { display: grid; gap: var(--sc-2); }
.ledger label {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--sc-ink-soft);
}
.ledger input, .ledger textarea, .ledger select {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: 0; border-bottom: 1px solid var(--sc-hairline-strong);
  border-radius: 0; padding: .5rem 0; width: 100%;
  font-family: var(--sc-font-text); font-size: var(--sc-t-base); color: var(--sc-ink);
  transition: border-color 140ms var(--sc-ease-out);
}
.ledger textarea { resize: vertical; min-height: 3.4rem; line-height: 1.5; }
.ledger :is(input, textarea, select):focus-visible {
  outline: none; border-bottom-color: var(--sc-accent); border-bottom-width: 2px;
  padding-bottom: calc(.5rem - 1px);
}
.ledger ::placeholder { color: var(--sc-ink-soft); opacity: .55; }
.ledger__pair { display: grid; gap: var(--sc-5); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 600px) { .ledger__pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ledger__hint { font-size: var(--sc-t-xs); color: var(--sc-ink-soft); margin: 0; }

/* The action is typographic. A filled coloured pill is the single most
   template-looking object on a page like this, so the ask is set in the book
   face, underscored by an inked rule, and sealed. */
.cta {
  justify-self: start; display: inline-flex; align-items: baseline; gap: .7rem;
  background: none; border: 0; padding: .35rem 0 .5rem; cursor: pointer;
  color: var(--sc-ink); text-decoration: none;
  font-family: var(--sc-font-display); font-size: var(--sc-t-lg);
  letter-spacing: var(--sc-track-snug); line-height: 1.1;
  border-bottom: 1px solid var(--sc-ink);
  transition: color 160ms var(--sc-ease-out), border-color 160ms var(--sc-ease-out);
}
.cta::after {
  content: ""; align-self: center;
  width: .46rem; height: .46rem; background: var(--sc-accent);
  transition: transform 200ms var(--sc-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .cta:hover { color: var(--sc-accent); border-color: var(--sc-accent); }
  .cta:hover::after { transform: translateX(.3rem); }
}
.cta--ghost {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  border-bottom-color: var(--sc-hairline-strong);
}
.cta--sm { font-size: var(--sc-t-base); }

.contact { display: grid; gap: var(--sc-4); align-content: start; }
@media (min-width: 900px) { .inquiry .contact { padding-top: max(0px, calc(var(--lai-chrome) - 7.5rem)); } }
.contact dl { margin: 0; display: grid; grid-template-columns: 6.5rem 1fr; gap: var(--sc-2) var(--sc-3); }
.contact dt {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--sc-ink-soft);
}
.contact dd { margin: 0; font-size: var(--sc-t-sm); }
.contact a { color: var(--sc-ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.contact a:hover { color: var(--sc-accent); }
.foot {
  margin-top: var(--sc-5); padding-top: var(--sc-4);
  border-top: 1px solid var(--sc-hairline-strong);
  display: flex; flex-wrap: wrap; gap: var(--sc-3) var(--sc-6);
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--sc-ink-soft);
}
.foot a { color: inherit; text-decoration: none; }
.foot a:hover { color: var(--sc-ink); }
.foot__by {
  margin-left: auto; opacity: .8;
  text-transform: none;
  letter-spacing: var(--sc-track-normal);
}
.foot__by [aria-hidden] { font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; }
.foot__by a { color: var(--sc-ink-soft); text-decoration: underline; text-underline-offset: 3px; }
.foot__by a:hover { color: var(--sc-accent); }
@media (max-width: 899px) { .foot__by { margin-left: 0; } }

/* ------------------------------------------------------------- mobile -- */
.book-fixed { display: none; }
@media (max-width: 899px) {
  .index { display: none; }

  /* On a phone the bar carries the mark alone. The name and the line under it
     are not hidden with display:none: this is the page's h1, so the words stay
     in the accessible name and in the document outline — they are only taken
     out of the picture. */
  .mark a { grid-template-areas: "logo"; grid-template-columns: auto; column-gap: 0; }
  .mark__rule { display: none; }
  .mark__name, .mark small {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .mark__logo { width: clamp(4rem, 13vw, 5.4rem); }
  /* One word and a mark. "Request a session" is the right phrase for the page
     and the wrong one for a button that floats over the work the whole way
     down: it was 190px of chrome sitting on the photographs. The full phrase
     stays as the button's accessible name. */
  .book-fixed {
    display: inline-flex; align-items: center; gap: .45rem;
    position: fixed; z-index: var(--sc-z-chrome);
    right: var(--sc-gutter); bottom: calc(var(--sc-4) + env(safe-area-inset-bottom));
    background: var(--sc-ink); color: var(--lai-paper);
    font-family: var(--sc-font-mono); font-size: var(--sc-t-xs); font-weight: 500;
    letter-spacing: var(--sc-track-wide); text-transform: uppercase;
    text-decoration: none; padding: .7rem .85rem;
    box-shadow: 0 10px 26px -14px hsl(var(--sc-shadow-color) / .7);
  }
  .book-fixed::before {
    content: ""; width: .4rem; height: .4rem; background: var(--sc-accent);
  }
  .card { max-width: none; padding: var(--sc-4); }
  .card--bl { right: var(--sc-gutter); bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
  .card--tr { left: var(--sc-gutter); right: var(--sc-gutter); top: auto; bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
  .rule-sec { min-height: 58vh; }
  .inquiry { padding-bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
  .card__title { font-size: var(--sc-t-lg); }
  .piece,
  .piece--tall, .piece--short, .piece--wide { width: 74vw; }
  .piece figure,
  .piece--tall figure, .piece--short figure, .piece--wide figure { height: 42vh; }
  .piece--drop, .piece--rise { margin-block: 0; }

  /* a pinned act has exactly one screen, and a phone screen is the tightest
     budget on the page: the studio act overflowed it and slid its own top
     under the fixed chrome, so everything in it is smaller and denser here */
  .process-stage, .studio-stage {
    padding: var(--lai-chrome) 0 calc(5.8rem + env(safe-area-inset-bottom));
  }
  .studio-stage .maker { gap: var(--sc-5); }
  .studio-stage .maker img { max-height: 26vh; }
  .studio-stage .plate-h { font-size: var(--sc-t-lg); }
  .studio-stage .note { font-size: var(--sc-t-xs); }
  .facts { gap: var(--sc-3); padding-top: var(--sc-3); }
  .facts .spec { grid-template-columns: 5rem 1fr; gap: 1px var(--sc-3); }
  .facts .spec dd { font-size: var(--sc-t-xs); }

  /* the drawn line is a six-column device. Over a two-column grid it runs
     through the copy instead of above it, so the phone gets the same idea as
     a rule inked down the left of each step. */
  .process__line { display: none; }
  .process__steps { padding-top: 0; gap: var(--sc-5) var(--sc-4); }
  .step { padding-left: var(--sc-4); border-left: 1px solid var(--sc-hairline-strong); }
  .process__creed { font-size: clamp(1.6rem, 8vw, 2.4rem); }
  .make--proc img { max-height: 18vh; aspect-ratio: 16 / 9; }
  .rail__lead, .rail__end { width: 74vw; }
  :root { --lai-band: 20vh; }
}

/* ------------------------------------------------- the archive strip -- */
/* Two rows deep, panning past at contact-sheet size. Deliberately not the
   collection rail: smaller, unlabelled beyond the number, read as volume. */
.strip {
  display: flex; align-items: center; gap: var(--sc-6);
  height: 100%; box-sizing: border-box;
  padding-inline: var(--sc-gutter);
  will-change: transform;
}
.strip__lead {
  flex: 0 0 auto; width: min(18rem, 76vw);
  display: flex; flex-direction: column; gap: var(--sc-4); align-items: flex-start;
}
.strip__sheet {
  flex: 0 0 auto;
  display: grid; grid-auto-flow: column; grid-template-rows: 1fr 1fr;
  gap: var(--sc-3);
  height: min(100%, 30rem);
}
.tile {
  position: relative; display: block; width: clamp(10rem, 16vw, 13.5rem);
  background: var(--sc-surface); overflow: clip; text-decoration: none;
}
.tile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tile__no {
  position: absolute; left: 0; bottom: 0;
  padding: 3px 6px; background: color-mix(in srgb, var(--lai-paper) 88%, transparent);
  font-family: var(--sc-font-mono); font-size: 10px;
  letter-spacing: var(--sc-track-wide); text-transform: uppercase; color: var(--sc-ink-soft);
}
@media (hover: hover) and (pointer: fine) {
  .tile img { transition: transform 300ms var(--sc-ease-out); }
  .tile:hover img { transform: scale(1.04); }
  .tile:hover .tile__no { color: var(--sc-ink); }
}
@media (max-width: 899px) {
  .strip__lead { width: 74vw; }
  .strip__sheet { height: min(100%, 22rem); }
  .tile { width: 9.5rem; }
  /* a phone should not inherit desktop air, and the page still has to land
     inside the length budget once every row has stacked */
  .maker img, .healed img { max-height: 30vh; }
  .maker { gap: var(--sc-8); }
}

/* ------------------------------------------------- stills that move -- */
/* Two ways to animate a photograph without a single byte of video, both
   driven by the act's own --sc-p, both transform/opacity only. */

/* 1. The hero pushes in under the hand. Six percent across the whole act:
      enough that the frame is alive, not enough to notice as an effect. */
.plate__img--hero {
  transform: scale(calc(1 + var(--sc-p, 0) * 0.06));
  transform-origin: 50% 42%;
  will-change: transform;
}

/* 2. The making shot settles rather than pushes: it starts a touch large and
      comes to rest, which is the opposite direction to the hero so the two
      never read as the same move. */
.make { position: relative; overflow: clip; }
.make img {
  transform: scale(calc(1.05 - var(--sc-p, 0) * 0.05));
  transform-origin: 50% 50%;
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .plate__img--hero { transform: none; }
  .make img { transform: none; }
  .process__line .inked { stroke-dashoffset: 0; }
  .step { opacity: 1; }
}

/* Facts the studio has not confirmed yet. Visible on purpose: a bracket is
   better than a plausible invention. Delete the class with the real value. */
.todo { color: var(--sc-accent); font-variant-numeric: normal; }

/* The signature, at the size it was drawn for, on the last screen. It is
   inked in rather than faded in: a mask sweeps left to right across the mark
   the way the stroke was originally laid down. */
.sign {
  /* the type alone: the calligraphic mark is already the page's wordmark, and
     repeating it here said the same thing twice */
  width: min(16rem, 60vw); aspect-ratio: 900 / 358;
  margin: var(--sc-6) auto 0;
  background: currentColor; color: var(--sc-ink-soft); opacity: .62;
  -webkit-mask: url("assets/wordmark.png?v=29dd8d57") center / contain no-repeat;
  mask: url("assets/wordmark.png?v=29dd8d57") center / contain no-repeat;
}

/* ===================================================== two languages == */
/* Both languages live in the markup. The root lang attribute decides which
   one paints, so there is no flash of the wrong language and no JS needed to
   render either one. */
html[lang="en"] [lang="lo"]:not(.lang button),
html[lang="lo"] [lang="en"]:not(.lang button) { display: none; }

/* Lao stacks vowels and tone marks above and below the line, so it needs more
   leading than Latin at the same size, and it must never be letter-spaced. */
[lang="lo"] {
  font-family: "Noto Sans Lao", var(--sc-font-text), sans-serif;
  letter-spacing: 0;
  line-height: 1.7;
  word-break: normal;
  line-break: normal;
}
:is(h1, h2, h3, .plate-h, .card__title, .rule-h, .arch-head h2, .process__creed, .healed .h-age) [lang="lo"] { line-height: 1.32; }
:is(.sc-label, .eyebrow, .card__no, .index a, .filters button, .foot, .cta, .spec dt, .contact dt, .ledger label, .step__n, .healed .h-no) [lang="lo"] {
  text-transform: none;   /* Lao has no case; uppercase does nothing but break shaping */
  font-size: 1.06em;
}
/* the display face carries no Lao, so Lao headings fall back to the Lao text
   face at a weight that still reads as a heading */
:is(.plate-h, .card__title, .rule-h, .process__creed, .mark__name, .cta, .healed .h-age) [lang="lo"] { font-weight: 500; }

/* the switch itself */
.chrome__right { display: flex; flex-direction: column; align-items: flex-end; }
.lang {
  display: inline-flex; align-items: center; gap: .35rem;
  margin: var(--sc-3) 0 0;
}
.lang button {
  appearance: none; background: none; border: 0; padding: 2px 0; cursor: pointer;
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft);
  border-bottom: 1px solid transparent;
  transition: color 140ms var(--sc-ease-out), border-color 140ms var(--sc-ease-out);
}
.lang button[aria-pressed="true"] { color: var(--sc-ink); border-bottom-color: var(--sc-accent); }
@media (hover: hover) and (pointer: fine) { .lang button:hover { color: var(--sc-ink); } }
.lang span { color: var(--sc-ink-soft); opacity: .5; }
.lang button[lang="lo"] { font-family: "Noto Sans Lao", sans-serif; text-transform: none; }

/* ------------------------------------------- photographs that lift off -- */
/* A torn front travels up the picture and eats it in flecks: the mask is a
   pre-generated sprite, so nothing is computed per frame, and two layers carry
   adjacent steps of it cross-blended so the front moves continuously. Applied
   to the full back on its way out, and to the healed row on its way to the
   studio. */
.erode-on .erode__a,
.erode-on .erode__b {
  -webkit-mask-image: url("assets/dissolve.png?v=b9e79514");
          mask-image: url("assets/dissolve.png?v=b9e79514");
  -webkit-mask-size: 100% var(--erode-h); mask-size: 100% var(--erode-h);
  -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
}
.erode-on .erode__a { -webkit-mask-position: 0 var(--fa, 0%); mask-position: 0 var(--fa, 0%); }
.erode-on .erode__b {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; max-width: none;
  opacity: var(--f, 0);
  -webkit-mask-position: 0 var(--fb, 0%); mask-position: 0 var(--fb, 0%);
}
/* the box exists only so the second layer has something to be absolute inside.
   In a full-bleed stage it has to fill the frame, or the picture inside it —
   which is absolutely positioned — resolves against a zero-height box and
   disappears. In the healed row it is a flex child instead. */
.erode__box { position: relative; display: block; }
.erode__lift .erode__box { position: absolute; inset: 0; }
.healed__row .erode__box { flex: 1 1 0; min-height: 0; overflow: hidden; }
.erode-on .plate__img--peak, .erode-on .erode__b { object-position: 50% 46%; }
.healed__row .erode__b { object-position: 50% 50%; }

/* what is left lifts and cools as it goes, so it reads as coming away from the
   page rather than being switched off */
.erode-on .erode__lift,
.erode-on .healed__row {
  transform: translate3d(0, calc(var(--lift, 0) * -3.2vh), 0) scale(calc(1 - var(--lift, 0) * -0.03));
  filter: brightness(calc(1 - 0.28 * var(--lift, 0))) contrast(calc(1 + 0.1 * var(--lift, 0)));
  will-change: transform, filter;
}
.erode-on .erode__lift { position: absolute; inset: 0; }
/* the captions go with their pictures */
.erode-on .healed__row figcaption { opacity: calc(1 - var(--lift, 0)); }

@media (prefers-reduced-motion: reduce) {
  .plate__img--hero { transform: none; }
  .make img { transform: none; }
  .process__line .inked { stroke-dashoffset: 0; }
  .step { opacity: 1; }
}

/* Facts the studio has not confirmed yet. Visible on purpose: a bracket is
   better than a plausible invention. Delete the class with the real value. */
.todo { color: var(--sc-accent); font-variant-numeric: normal; }

/* The signature, at the size it was drawn for, on the last screen. It is
   inked in rather than faded in: a mask sweeps left to right across the mark
   the way the stroke was originally laid down. */
.sign {
  /* the type alone: the calligraphic mark is already the page's wordmark, and
     repeating it here said the same thing twice */
  width: min(16rem, 60vw); aspect-ratio: 900 / 358;
  margin: var(--sc-6) auto 0;
  background: currentColor; color: var(--sc-ink-soft); opacity: .62;
  -webkit-mask: url("assets/wordmark.png?v=29dd8d57") center / contain no-repeat;
  mask: url("assets/wordmark.png?v=29dd8d57") center / contain no-repeat;
}
@media (prefers-reduced-motion: no-preference) {
  .sign {
    -webkit-mask-composite: source-in; mask-composite: intersect;
    -webkit-mask-image: url("assets/wordmark.png?v=29dd8d57"),
      linear-gradient(100deg, #000 calc(var(--wr, 0) * 132% - 22%), transparent calc(var(--wr, 0) * 132% - 4%));
    mask-image: url("assets/wordmark.png?v=29dd8d57"),
      linear-gradient(100deg, #000 calc(var(--wr, 0) * 132% - 22%), transparent calc(var(--wr, 0) * 132% - 4%));
    -webkit-mask-size: contain, 100% 100%; mask-size: contain, 100% 100%;
    -webkit-mask-repeat: no-repeat, no-repeat; mask-repeat: no-repeat, no-repeat;
    -webkit-mask-position: center, center; mask-position: center, center;
  }
}

/* ===================================================== two languages == */
/* Both languages live in the markup. The root lang attribute decides which
   one paints, so there is no flash of the wrong language and no JS needed to
   render either one. */
html[lang="en"] [lang="lo"]:not(.lang button),
html[lang="lo"] [lang="en"]:not(.lang button) { display: none; }

/* Lao stacks vowels and tone marks above and below the line, so it needs more
   leading than Latin at the same size, and it must never be letter-spaced. */
[lang="lo"] {
  font-family: "Noto Sans Lao", var(--sc-font-text), sans-serif;
  letter-spacing: 0;
  line-height: 1.7;
  word-break: normal;
  line-break: normal;
}
:is(h1, h2, h3, .plate-h, .card__title, .rule-h, .arch-head h2, .process__creed, .healed .h-age) [lang="lo"] { line-height: 1.32; }
:is(.sc-label, .eyebrow, .card__no, .index a, .filters button, .foot, .cta, .spec dt, .contact dt, .ledger label, .step__n, .healed .h-no) [lang="lo"] {
  text-transform: none;   /* Lao has no case; uppercase does nothing but break shaping */
  font-size: 1.06em;
}
/* the display face carries no Lao, so Lao headings fall back to the Lao text
   face at a weight that still reads as a heading */
:is(.plate-h, .card__title, .rule-h, .process__creed, .mark__name, .cta, .healed .h-age) [lang="lo"] { font-weight: 500; }

/* the switch itself */
.chrome__right { display: flex; flex-direction: column; align-items: flex-end; }
.lang {
  display: inline-flex; align-items: center; gap: .35rem;
  margin: var(--sc-3) 0 0;
}
.lang button {
  appearance: none; background: none; border: 0; padding: 2px 0; cursor: pointer;
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft);
  border-bottom: 1px solid transparent;
  transition: color 140ms var(--sc-ease-out), border-color 140ms var(--sc-ease-out);
}
.lang button[aria-pressed="true"] { color: var(--sc-ink); border-bottom-color: var(--sc-accent); }
@media (hover: hover) and (pointer: fine) { .lang button:hover { color: var(--sc-ink); } }
.lang span { color: var(--sc-ink-soft); opacity: .5; }
.lang button[lang="lo"] { font-family: "Noto Sans Lao", sans-serif; text-transform: none; }

/* --------------------------------------------- the piece lifts off the skin -- */
/* The peak holds fully inked, then the photograph comes away the way a stencil
   transfer does: a torn front travels up the frame and eats it in flecks.
   The erosion is a pre-generated mask sprite, so nothing is computed per frame,
   and two layers carry adjacent steps of the sprite cross-blended, so the front
   moves continuously instead of stepping. */
.plate--erode .plate__img--peak,
.plate--erode .erode__b {
  -webkit-mask-image: url("assets/dissolve.png?v=b9e79514");
          mask-image: url("assets/dissolve.png?v=b9e79514");
  -webkit-mask-size: 100% var(--erode-h); mask-size: 100% var(--erode-h);
  -webkit-mask-repeat: no-repeat;         mask-repeat: no-repeat;
}
.plate--erode .plate__img--peak { -webkit-mask-position: 0 var(--fa, 0%); mask-position: 0 var(--fa, 0%); }
.erode__b {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 46%; max-width: none;
  opacity: var(--f, 0);
  -webkit-mask-position: 0 var(--fb, 0%); mask-position: 0 var(--fb, 0%);
}
.plate--erode .erode__lift {
  position: absolute; inset: 0;
  transform: translate3d(0, calc(var(--lift, 0) * -3.2vh), 0) scale(calc(1 + var(--lift, 0) * 0.03));
  filter: brightness(calc(1 - 0.28 * var(--lift, 0))) contrast(calc(1 + 0.1 * var(--lift, 0)));
  will-change: transform, filter;
}

/* --------------------------------------------------- lateral damping -- */
/* A wheel does not deliver even ticks, so a rail written straight from scroll
   arrives in steps. A short ease on the transform lets the rail glide the last
   few pixels and reads as weight rather than lag. Desktop pointers only: touch
   scrolling is already continuous, and there the same easing would make the
   rail trail the thumb. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .rail, .strip { transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1); }
}

/* ------------------------------------------------- healed: a held stop -- */
/* The act pins and the three photographs arrive one at a time, so the claim
   ("ask to see it a year later") has time to be tested by the pictures rather
   than passed on the way to the next section. */
/* The healed act hands over to the studio, which is paper. Left alone that is
   a hard cut: the paper stage slides up over the plate one and the ground
   changes in a single frame. Instead the stage washes its own ground from
   plate to paper as it lets go, so the change is a transition rather than an
   edge — and by the time the studio arrives the ground already matches it. */
.healed-stage.stage--plate {   /* both classes: the plain .stage--plate rule is later in the file */
  background: color-mix(in srgb, var(--lai-paper) calc(var(--wash, 0) * 100%), var(--lai-plate));
}
.healed-stage {
  display: grid; align-content: center; box-sizing: border-box;
  /* clear the fixed wordmark: the stage is centred in what is left, not in the
     whole viewport, or the heading runs under the chrome */
  padding: 7rem var(--sc-gutter) var(--sc-6);
}
.healed-stage .healed { width: 100%; }
.healed-stage .healed__head { margin-bottom: var(--sc-4); }
.healed-stage .healed__head .note { display: none; }  /* the pictures make this point; the paragraph repeated it */
.healed-stage .healed__row figure img { max-height: 26vh; object-fit: cover; }
.healed-stage .healed > .note.todo { margin-top: var(--sc-4); }

@media (max-width: 759px) {
  .healed-stage { padding-top: calc(var(--lai-chrome) + 1.6rem); padding-bottom: 5rem; }
  /* three stacked photographs cannot fit one screen, so on a phone they take
     turns in the same frame. Every figure is the SAME box, image and caption
     together: unequal boxes let the one underneath show past the one on top,
     which read as a broken collage rather than a sequence. */
  .healed-stage .healed__row {
    display: grid; grid-template-areas: "frame"; height: 42vh; min-height: 0;
  }
  .healed-stage .healed__row > figure {
    grid-area: frame; margin: 0; height: 100%; overflow: hidden;
    display: flex; flex-direction: column; gap: var(--sc-3);
    /* in AND out: stacked in one frame they must hand over, or all three end
       at full opacity and three captions paint on top of each other */
    opacity: clamp(0, min(calc((var(--sc-p, 0) - var(--in)) * 9),
                          calc((var(--out) - var(--sc-p, 0)) * 9)), 1);
    transition: none;
    /* the engine's wipe reveals a figure from the bottom up, which on a phone
       means the one underneath shows through the part not yet revealed: two
       photographs in one frame. Stacked, the fade alone carries the change. */
    clip-path: none !important;
  }
  .healed-stage .healed__row figure img {
    /* the 4:5 ratio from the desktop rule outgrows the frame here and pushes
       the caption out of the figure, where it lands on the note below */
    aspect-ratio: auto;
    /* flex-basis 0 so the picture yields to the caption instead of pushing it
       out of the frame; height auto lets the flex line do the sizing */
    flex: 1 1 0; min-height: 0; width: 100%; height: auto;
    max-height: none; object-fit: cover;
  }
  .healed-stage .healed__row figcaption { flex: 0 0 auto; }
}
@media (prefers-reduced-motion: reduce) {
  .healed-stage .healed__row > figure { opacity: 1; }
}

/* ===================================================== the phone pass ===== */
/* Measured at 390x844. Two things were actually broken rather than tight: the
   process act and the closing form both overflowed a pinned stage, so their
   last rows were clipped and unreachable. The rest is type: a display scale
   built for a 1440 column is a rung too loud on a phone, and 14px body is a
   rung too quiet. */
@media (max-width: 759px) {
  /* display steps down, body steps up */
  .plate-h,
  .healed-stage .healed__head h2 { font-size: clamp(1.5rem, 6.8vw, 1.95rem); line-height: 1.1; }
  .rule-h { font-size: clamp(1.75rem, 8vw, 2.3rem); }
  .card__title { font-size: 1.08rem; line-height: 1.18; }
  .note, .spec dd, .contact dd, .ask ol li { font-size: 0.95rem; }
  .arch-head h2 { font-size: clamp(1.7rem, 8vw, 2.2rem); }

  /* a thumb needs something to hit: text links were rendering 15px tall */
  .contact dd a, .spec dd a, .ledger a, .foot a, .foot__by a,
  .index a, .lang button {
    display: inline-block; padding-block: 0.4rem;
  }
  .cta, .cta--ghost { padding-block: 0.85rem; }

  /* the process act: the macro shot and six steps cannot share one screen, and
     the shot is making the same point the steps make in words */
  .process-stage .make--proc { display: none; }
  .process-stage .process { gap: var(--sc-4); }
  .process-stage .process__creed { font-size: clamp(1.35rem, 6.2vw, 1.7rem); line-height: 1.12; }
  .process-stage .process__step h3 { font-size: 1rem; }
  .process-stage .process__step p { font-size: 0.88rem; }

  /* every pinned stage has to clear the wordmark, which is ~114px down */
  .process-stage, .studio-stage { padding-top: calc(var(--lai-chrome) + 1.6rem); padding-bottom: var(--sc-5); }
  .process-stage .process__step p { line-height: 1.45; }
  .process-stage .process__track { gap: var(--sc-3) var(--sc-5); }

  /* The close asks for a form, five contact rows, the signature and a footer.
     That is a page, not a screen, so on a phone it stops being a held stage
     and simply scrolls: nothing is clipped and nothing has to shrink. */
  #session [data-sc-stage] {
    position: static; height: auto; min-height: 0; overflow: visible;
  }
  .inquiry { height: auto; padding-block: calc(var(--lai-chrome) + 2rem) var(--sc-7); }
  .inquiry__grid { gap: var(--sc-6); }
  .inquiry .ledger__row { margin-bottom: var(--sc-3); }
  .sign { width: min(18rem, 62vw); }
}

/* ================================================ paper, plate, paper ==== */
/* The page alternates ground: every act either sits on paper or on plate, and
   nothing in between. Each stage paints its own, because the engine's drift is
   always a beat behind a full-screen stage and that gap is exactly where ink
   lands on the wrong ground. */
[data-sc-stage] { background: var(--lai-paper); }
.obj .plate, .stage--plate { background: var(--lai-plate); }

.stage--plate {
  /* the hairline tokens are color-mixed from --sc-ink ON :root, so they are
     already computed by the time a subtree overrides the ink: without
     restating them a plate stage draws paper-ink hairlines, which is to say
     none at all. The closing act's form underlines had disappeared. */
  --sc-hairline:        color-mix(in oklab, var(--lai-plate-ink) 16%, transparent);
  --sc-hairline-strong: color-mix(in oklab, var(--lai-plate-ink) 30%, transparent);
  --sc-ink:        var(--lai-plate-ink);
  --sc-ink-soft:   var(--lai-plate-soft);
  --sc-surface:    var(--lai-plate-surface);
  --sc-accent:     var(--lai-accent-plate);
  --sc-shadow-color: 30 20% 2%;
  color: var(--sc-ink);           /* colour is inherited computed, so restate it */
}

/* a label card is a piece of paper wherever it is pinned, so it keeps the
   paper ink even when the stage around it has gone dark */
.card {
  --sc-ink:      var(--lai-ink);
  --sc-ink-soft: var(--lai-ink-soft);
  --sc-accent:   var(--lai-accent);
  color: var(--sc-ink);
}

@media (max-width: 899px) {
  /* the fixed booking pill is ink-on-paper, which disappears into a plate
     ground. On dark it inverts: a stamp of paper on the photograph. */
  [data-plate="dark"] .book-fixed {
    background: var(--lai-paper); color: var(--lai-ink);
  }
  [data-plate="dark"] .book-fixed .dot,
  [data-plate="dark"] .book-fixed span[aria-hidden] { background: var(--lai-accent); }
}

/* ======================================================= scroll as steps == */
/* On the acts that hold — the process, healed, the studio — scroll does not
   smear content in, it lands it. A stepper quantises the act's progress to an
   integer and each part waits for its number to come up, then arrives on its
   own clock. That is what makes it read as a step rather than a fade: the
   movement is timed, not scrubbed, so it happens TO you rather than under your
   finger.
   --step is the act's current number, --at is the part's own. The rules are
   scoped to .steps-on, which only the script adds: with no JS every part is
   simply there, which is the right fallback for a page made of real markup. */
[data-lai-steps].steps-on :is(.step, .healed__row > figure, .studio-stage [style*="--at"]) {
  /* 1 as soon as the act reaches this part's number, 0 before it */
  --on: clamp(0, calc(var(--step, 0) - var(--at, 0) + 1), 1);
  opacity: var(--on);
  transform: translate3d(0, calc((1 - var(--on)) * 15px), 0);
  transition: opacity 460ms var(--sc-ease-out), transform 520ms var(--sc-ease-out);
  will-change: opacity, transform;
}
/* the part carrying number 0 is the ground: it is there when the act arrives */
[data-lai-steps].steps-on [style*="--at: 0"] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-lai-steps].steps-on :is(.step, .healed__row > figure, .studio-stage [style*="--at"]) {
    opacity: 1; transform: none; transition: none;
  }
}

@media (max-width: 759px) {
  /* the healed prints share one frame on a phone, so a print leaves when the
     next one lands instead of stacking up */
  /* :is() takes the specificity of its most specific argument, so the base
     rule above outranked this one and the hand-over never applied */
  .healed-stage[data-lai-steps].steps-on .healed__row > figure {
    --on: clamp(0, min(calc(var(--step, 0) - var(--at, 0) + 1),
                       calc(var(--at, 0) - var(--step, 0) + 1)), 1);
  }
}

/* ============================================== the request, one at a time == */
/* A sheet of paper on a dimmed plate, which is the page's own metaphor: a label
   card is paper wherever it is pinned. The card lands on the same ease as the
   acts that hold, so the modal reads as part of the page rather than a widget
   bolted to it. */
/* No position on the dialog itself: setting it takes the element out of the
   browser's modal placement and it lands wherever it happens to sit in the
   document — 12,000px up the page, in this one's case. The close button
   anchors to the sheet instead. */
.ask-modal {
  border: 0; padding: 0; background: none;
  max-width: min(34rem, 92vw); width: 100%;
  color: var(--lai-ink);
}
/* literal, not a token: ::backdrop is not a descendant of the dialog, so in
   several engines a var() here resolves to nothing and the whole declaration is
   dropped — leaving the page undimmed behind the sheet. #12100D is --lai-plate. */
.ask-modal::backdrop { background: rgba(18, 16, 13, .90); }
.ask-modal__sheet {
  position: relative;
  background: var(--lai-paper);
  padding: var(--sc-7) var(--sc-6) var(--sc-6);
  box-shadow: 0 30px 70px -30px hsl(var(--sc-shadow-color) / .8);
  --sc-ink: var(--lai-ink); --sc-ink-soft: var(--lai-ink-soft); --sc-accent: var(--lai-accent);
}
.ask-modal__sheet.is-in {
  animation: ask-land 460ms var(--sc-ease-out) both;
}
@keyframes ask-land {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}
.ask-modal__count {
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--lai-accent); margin: 0 0 var(--sc-4);
  padding-bottom: var(--sc-3); border-bottom: 1px solid var(--sc-hairline-strong);
}
.ask-modal__q {
  font-family: var(--sc-font-display); font-weight: 400;
  font-size: clamp(1.5rem, 4.4vw, 2rem); line-height: 1.08;
  letter-spacing: var(--sc-track-tight); margin: 0 0 var(--sc-3);
  text-wrap: balance;
}
.ask-modal__hint { font-size: var(--sc-t-sm); color: var(--sc-ink-soft); margin: 0 0 var(--sc-4); max-width: 40ch; }
.ask-modal__field { margin-bottom: var(--sc-4); }
.ask-modal__field :is(input, textarea) {
  width: 100%; box-sizing: border-box;
  font-family: var(--sc-font-text); font-size: 1rem; color: var(--lai-ink);
  background: none; border: 0; border-bottom: 1px solid var(--sc-hairline-strong);
  padding: var(--sc-3) 0; border-radius: 0; resize: vertical;
}
.ask-modal__field :is(input, textarea)::placeholder { color: color-mix(in srgb, var(--lai-ink-soft) 70%, transparent); }
.ask-modal__field :is(input, textarea):focus-visible {
  outline: none; border-bottom-color: var(--lai-accent);
}
.ask-modal__warn { font-size: var(--sc-t-sm); color: var(--lai-accent); margin: 0 0 var(--sc-3); }
.ask-modal__nav { display: flex; align-items: center; gap: var(--sc-4); }
.ask-modal__back {
  appearance: none; background: none; border: 0; cursor: pointer; padding: .6rem 0;
  font-family: var(--sc-font-mono); font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide); text-transform: uppercase;
  color: var(--sc-ink-soft);
}
.ask-modal__back:hover { color: var(--lai-ink); }
.ask-modal__next { margin-left: auto; cursor: pointer; }
.ask-modal__x { position: absolute; top: 0; right: 0; margin: 0; z-index: 1; }
.ask-modal__close {
  appearance: none; background: none; border: 0; cursor: pointer;
  width: 2.75rem; height: 2.75rem;          /* a thumb-sized target, not a glyph */
  position: relative;
}
.ask-modal__close::before, .ask-modal__close::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 14px; height: 1px; background: var(--lai-ink-soft);
}
.ask-modal__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.ask-modal__close::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.ask-modal__close:hover::before, .ask-modal__close:hover::after { background: var(--lai-accent); }

@media (max-width: 759px) {
  .ask-modal { max-width: calc(100% - 2 * var(--sc-gutter)); }
  .ask-modal__sheet { padding: var(--sc-6) var(--sc-5) var(--sc-5); }
}
@media (prefers-reduced-motion: reduce) {
  .ask-modal__sheet.is-in { animation: none; }
}

/* The close carries a form, five contact rows, the signature and a footer.
   That fits a 900px screen and not a 760px one, and a pinned stage clips what
   it cannot fit. So the rule is about height, not width: when the screen is
   too short the act stops being held and simply scrolls, exactly as it does
   on a phone. */
@media (max-height: 860px) and (min-width: 900px) {
  #session [data-sc-stage] { position: static; height: auto; min-height: 0; overflow: visible; }
  .inquiry { height: auto; padding-block: 7.5rem var(--sc-7); }
}
