/* ============================================================
   v2c: v2 with the On Process story full bleed (Michael, 2026-10-03).
   v2: v1's layout set in v4's type (Michael, 2026-10-03).
   v2b is the same page in Instrument Serif, for comparison.

   - Bodoni Moda: the Didone of Vogue and Harper's Bazaar, with
     optical sizes so its hairlines hold. the hero title and the
     line under it, section headings, the pull quote, the form's
     questions.
   - Archivo: a grotesk with a width axis. body copy at normal
     width; eyebrows, the name and the location stretched wide.
   ============================================================ */

:root{
  --display:'Bodoni Moda', 'Didot', 'Bodoni 72', Georgia, serif;
  --sans:'Archivo', 'Helvetica Neue', system-ui, sans-serif;
}
body{font-family:var(--sans); font-weight:400}

/* ---------- wide grotesk caps: eyebrows, the name, the location ---------- */
.label{
  font-family:var(--sans); font-stretch:125%; font-weight:500;
  font-size:11px; line-height:16px; letter-spacing:.32em; color:var(--paper);
}
.top .t-name{font-family:var(--sans); font-stretch:125%; font-weight:300; font-size:13px; letter-spacing:.28em}
.t-nav, .vswitch a{font-family:var(--sans)}
.t-meta, .caption, .t-form, button, input[type=text], input[type=email], textarea, footer{font-family:var(--sans)}
.caption{font-size:13px; line-height:20px}

/* ---------- display: Bodoni ---------- */
.t-h1, .t-h2{font-family:var(--display); font-weight:400; font-optical-sizing:auto; letter-spacing:-.02em}
.t-h2{font-size:clamp(36px,4vw,64px); line-height:1.05}

/* ---------- reading: Archivo ---------- */
.wall{font-family:var(--sans); font-size:17px; line-height:28px; color:var(--paper-dim)}

/* ---------- the hero: title and the line under it in Bodoni, the
   location in the wide caps ---------- */
.hero__type{max-width:none}
.hero__type .t-intro{font-family:var(--display); font-style:normal; font-weight:400; letter-spacing:-.005em}
.hero__type .t-meta{
  font-family:var(--sans); font-stretch:125%; font-weight:500; font-size:11px; line-height:16px;
  letter-spacing:.32em; text-transform:uppercase; color:var(--paper);
}
@media (min-width:900px){
  .hero__type .t-h1{font-size:clamp(64px,6.4vw,104px); line-height:1.02}
  .hero__type .t-intro{font-size:clamp(20px,1.6vw,26px); line-height:1.35; max-width:30em}
}
@media (max-width:899px){
  .hero__type .t-h1{font-size:clamp(36px, calc((100vw - 48px) / 8.6), 46px); line-height:1.08}
  .hero__type .t-intro{font-size:21px; line-height:1.4; max-width:none}
  .hero__type .t-meta{font-size:13px; line-height:20px}
}

/* ---------- the weave: 50/50, the same photo as a portrait, the paragraph
   at pull-quote size in Bodoni italic ---------- */
@media (min-width:900px){
  .band--quote{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .band--quote .band__media{aspect-ratio:2 / 3; max-height:100svh}
}
.band--quote .band__media{aspect-ratio:2 / 3}
.band--quote .plate--edges{background-position:30% 50%}
.pullquote{
  margin:0; font-family:var(--display); font-style:italic; font-weight:400; font-optical-sizing:auto;
  font-size:clamp(28px,3.2vw,52px); line-height:1.16; letter-spacing:-.012em;
  color:var(--paper); text-wrap:pretty; max-width:22em;
}

/* ---------- the end: the form and footer fill the screen together ---------- */
section.opt{min-height:100svh; box-sizing:border-box}

/* ---------- phones: the vertical hero (IMG_3601), a little right of center
   to keep the red column in frame ---------- */
@media (max-width:899px){
  .hero .plate{background-position:58% 50%}
}

/* ---------- the inquiry form (ported from v4): questions in Bodoni ---------- */
section .inq{--inq-display:var(--display); --inq-q-size:clamp(28px,2.6vw,40px); --inq-q-weight:400}

/* ============================================================
   v2c: the On Process story, full bleed (Michael, 2026-10-03).
   the frame breaks out of the sheet to the screen edges and fills
   the pinned stage; the copy sits lower left, where the hero's does.
   the frame is sized to the tallest screen height (lvh) so iOS
   toolbars can't re-scale it; the copy is placed within the small
   screen height so it never hides behind them.
   ============================================================ */
.story--bleed{margin-inline:calc(-1 * var(--frame))}
.story--bleed .story__stage{display:block; padding:0; height:100svh; overflow:visible}
.story--bleed .story__inner{position:relative; width:100%; height:100%}
.story--bleed .story__frame{position:absolute; top:0; left:0; right:0; width:auto; height:100vh; height:100lvh; aspect-ratio:auto}
/* a gradient behind the copy only, dark at the foot, gone two thirds up */
.story--bleed .story__frame::after{content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to top, rgba(10,10,11,.88) 0%, rgba(10,10,11,.78) 28%,
    rgba(10,10,11,.5) 46%, rgba(10,10,11,0) 68%)}
.story--bleed .story__copy{position:absolute; z-index:2; margin:0;
  left:calc(var(--frame) + var(--pad)); right:calc(var(--frame) + var(--pad)); bottom:96px; max-width:620px}
.story--bleed .story__copy .wall{color:var(--paper)}
@media (max-width:899px){
  .story--bleed .story__copy{bottom:64px; padding-inline:0}
}

/* frame one: Adam's full RAW frame (color-matched to his JPEG). it zooms from the
   center of his crop (39% across, 47% down), so it opens on his framing */
.story--bleed .story__img--raw{object-position:39% 47%; transform-origin:39% 47%}

/* body copy in Newsreader (Michael, 2026-10-03), the editorial reading serif from v2b */
:root{--read:'Newsreader', 'Iowan Old Style', Georgia, serif}
.wall{font-family:var(--read); font-size:clamp(17px,1.3vw,19px); line-height:1.6; font-optical-sizing:auto}

/* the story sits inside the same 13px frame as every other section (Michael,
   2026-10-03): just short of full bleed. the copy stays on the page's rail. */
.story--bleed{margin-inline:0}
.story--bleed .story__copy{left:var(--pad); right:var(--pad)}
/* phones: the story goes full bleed again (Michael, 2026-10-03); desktop keeps the frame */
@media (max-width:899px){
  .story--bleed{margin-inline:calc(-1 * var(--frame))}
  .story--bleed .story__copy{left:calc(var(--frame) + var(--pad)); right:calc(var(--frame) + var(--pad))}
}

/* phones: In Place copy (eyebrow, heading, paragraph) above its photo (Michael, 2026-10-03) */
@media (max-width:899px){
  .band:has(> .band__fig) > .band__copy{order:-1; padding:0 var(--pad) 32px}
}

/* the story copy sits lower (Michael, 2026-10-03): 32px from the bottom on phones, 64 on
   desktop, so the gradient behind it can be shorter and the photos read brighter.
   one ease-in-out curve again, holding only under the copy. */
.story--bleed .story__copy{bottom:64px}
.story--bleed .story__frame::after{background:linear-gradient(to top, rgba(10,10,11,0.88) 0%, rgba(10,10,11,0.88) 14%, rgba(10,10,11,0.865) 17.0%, rgba(10,10,11,0.821) 20.0%, rgba(10,10,11,0.751) 23.0%, rgba(10,10,11,0.660) 26.0%, rgba(10,10,11,0.554) 29.0%, rgba(10,10,11,0.440) 32.0%, rgba(10,10,11,0.326) 35.0%, rgba(10,10,11,0.220) 38.0%, rgba(10,10,11,0.129) 41.0%, rgba(10,10,11,0.059) 44.0%, rgba(10,10,11,0.015) 47.0%, rgba(10,10,11,0.000) 50.0%)}
@media (max-width:899px){
  .story--bleed .story__copy{bottom:32px}
  .story--bleed .story__frame::after{background:linear-gradient(to top, rgba(10,10,11,0.88) 0%, rgba(10,10,11,0.88) 18%, rgba(10,10,11,0.865) 20.8%, rgba(10,10,11,0.821) 23.7%, rgba(10,10,11,0.751) 26.5%, rgba(10,10,11,0.660) 29.3%, rgba(10,10,11,0.554) 32.2%, rgba(10,10,11,0.440) 35.0%, rgba(10,10,11,0.326) 37.8%, rgba(10,10,11,0.220) 40.7%, rgba(10,10,11,0.129) 43.5%, rgba(10,10,11,0.059) 46.3%, rgba(10,10,11,0.015) 49.2%, rgba(10,10,11,0.000) 52.0%)}
}

/* phones: the rigidity image as a square (Michael, 2026-10-03). a square from a 3:2 photo
   uses its full height, so the in-focus beads stay centered top to bottom; across, the
   sharp cord column (34% of the photo) lands a little left of center with depth behind it */
@media (max-width:899px){
  .band--quote .band__media{aspect-ratio:1 / 1}
  .band--quote .plate--edges{background-position:15% 50%}
}
/* phones: zoomed so three full beads stand on the left column with the ones above and
   below cut off (bead pitch ~19% of the photo's height: the square shows 69% of it),
   centered on the middle bead, cord column at ~30% across (Michael, 2026-10-03) */
@media (max-width:899px){
  .band--quote .plate--edges{background-size:auto 145%; background-position:37% 60%}
}

/* ============================================================
   the end of the page (Michael, 2026-10-03): you can't scroll past the
   Commission + Collaboration section. it and the footer together fill one
   screen (footer ~100px), so at the furthest scroll the heading is still in
   view; if the form's details step needs more room, the page grows by only
   that much.
   ============================================================ */
section.opt{min-height:calc(100svh - 100px); padding-top:128px; padding-bottom:64px}
@media (max-width:899px){ section.opt{min-height:calc(100svh - 96px); padding-top:96px; padding-bottom:48px} }

/* labels inside the fields: ghosted where you type; on focus or once filled they shrink
   up into the top of the field instead of vanishing (a vanishing placeholder-label is a
   known usability problem, NN/g). saves a label line per field. */
.inq .inq-field{position:relative}
.inq .inq-field > .inq-field__label{
  position:absolute; left:0; right:0; top:24px; z-index:1; pointer-events:none;
  font-size:18px; line-height:28px; font-weight:400; letter-spacing:0; color:rgba(236,231,223,.62);
  transform-origin:0 0; transition:transform .24s var(--ease), color .24s var(--ease), top .24s var(--ease);
}
.inq .inq-field__opt{font-size:13px; color:rgba(236,231,223,.5)}
.inq .inq-field > .inq-field__box{margin-top:0; padding-top:16px}
.inq .inq-field:focus-within > .inq-field__label,
.inq .inq-field.is-filled > .inq-field__label{
  top:0; transform:scale(.72); color:var(--inq-dim)}
.inq .inq-field:focus-within > .inq-field__label .inq-field__opt,
.inq .inq-field.is-filled > .inq-field__label .inq-field__opt{opacity:0}
.inq .inq-field + .inq-field, .inq .inq-avail + .inq-field{margin-top:0}
.inq .inq-field__msg{margin-top:4px}
.inq .inq-field__help{margin-top:4px; margin-bottom:16px}
.inq .inq-field textarea + *, .inq .inq-avail .inq-field > .inq-field__box{padding-top:16px}
/* desktop: tighten so at the furthest scroll the heading clears the top bar */
@media (min-width:900px){
  section.opt{padding-top:112px; padding-bottom:16px}
  .inq .inq__nav{margin-top:16px}
  .inq .inq-send{margin-top:16px}
  .inq .inq-send__status{margin-top:8px}
}

/* short desktop windows (under 860px tall): the form holds only the current step's height
   instead of reserving room for the tallest, so the first question fits beside the heading
   and the page grows only when the details step arrives (Michael, 2026-10-03) */
@media (min-width:900px) and (max-height:859px){
  section.opt{padding-top:88px}
  .inq .inq-step:not(.is-on){display:none}
}

/* desktop: the rigidity image fills its whole half of the band as the screen widens,
   revealing more of the photo, instead of holding a 2:3 width capped by screen height and
   drifting to the edge (Michael, 2026-10-03). one height for the band. */
@media (min-width:900px){
  .band--quote .band__media{aspect-ratio:auto; max-height:none; height:min(100svh, max(640px, 72vw))}
  .band--quote .plate--edges{background-position:22% 50%}
}

/* ---------- hero, desktop (Michael, 2026-10-03) ----------
   copy moves 32px lower (two 16px steps); the title gets more line height so the g of
   "Weaving" and the f of "of" no longer touch; the line beneath is set in the reading
   serif (Newsreader) at a larger size and runs on one line, so the title stands out and
   the line reads as information. */
@media (min-width:900px){
  .hero__type{bottom:64px}
  .hero__type .t-h1{line-height:1.14}
  .hero__type .t-intro{font-family:var(--read); font-weight:400; font-size:clamp(22px,1.75vw,30px);
    line-height:1.4; letter-spacing:0; max-width:none; white-space:nowrap}
}
/* desktop: the title on one line (Michael, 2026-10-03). sized to fit the frame:
   at 1440 it spans ~70% of the width */
@media (min-width:900px){
  .hero__type .t-h1 br{display:none}
  .hero__type .t-h1{white-space:nowrap; font-size:clamp(56px,5.6vw,112px); line-height:1.05}
}

/* the hero title stands out (Michael, 2026-10-03): the row banding behind the copy, not
   the whole photo. stronger, and held to the copy's left: the ellipse sits at 38% across
   and stops shortly past the text on the right, so the bright blurred right side and the
   rest of the frame stay clean. plus a soft, invisible shadow on every letter. */
.hero__type{--band:.97; --spread-y:46%; --fade:56%}
.hero__type.fx-cyl::before{inset:calc(-1 * var(--spread-y)) -8% calc(-1 * var(--spread-y)) -14%;
  -webkit-mask-image:radial-gradient(ellipse 62% 54% at 38% 50%,
      #000 10%, rgba(0,0,0,.78) 34%, rgba(0,0,0,.38) 58%, rgba(0,0,0,.1) 78%, transparent 96%);
  mask-image:radial-gradient(ellipse 62% 54% at 38% 50%,
      #000 10%, rgba(0,0,0,.78) 34%, rgba(0,0,0,.38) 58%, rgba(0,0,0,.1) 78%, transparent 96%)}
.hero__type .t-h1, .hero__type .t-intro, .hero__type .t-meta{
  text-shadow:0 1px 2px rgba(6,6,7,.45), 0 0 18px rgba(6,6,7,.35)}

/* the hero photo aligned to the viewport's left edge (Michael, 2026-10-03) */
.hero .plate{background-position:0% 50%}

/* ---------- parked notes, 2026-10-04 (Michael) ---------- */
/* In Place, desktop: the room photo zoomed in a little (12%), held on the piece
   (52% across, 45% down). phones keep their own crop. */
@media (min-width:900px){
  .band--flip .plate{background-size:auto 112%; background-position:52% 45%}
}
/* the palette, shot from further away: its white extended in the image itself
   (desktop 3:2, phones a 1:2 portrait cut). the close-in still starts on the urchin. */
.story--bleed .story__img--palette{transform-origin:43% 33%}
@media (max-width:899px){ .story--bleed .story__img--palette{transform-origin:40% 27%} }
/* On Process, slower and calmer: a longer pin (420 → 520svh), so each change takes
   about a quarter more scroll. the script also eases the images after the scroll. */
@media (prefers-reduced-motion:no-preference){ .story{height:560svh} }  /* 460svh of pin, as v2b (2026-10-04) */

/* On Process, desktop: the treatment behind the copy only as dark as AA needs (Michael,
   2026-10-04). measured over every photo state through the scroll at 1024x768, 1280x720,
   1440x900 and 1920x1080: the resting paragraph text (64% white) is the limit, 4.62:1 at
   worst (5th percentile of the pixels behind it), label 9.3:1. .78 held to just above the
   copy (188px), one eased curve to nothing at 296px; set in px since the copy sits at a
   fixed distance from the bottom. was .88, fading out at half the screen. */
@media (min-width:900px){
  .story--bleed .story__frame::after{background:linear-gradient(to top, rgba(10,10,11,0.78) 0px, rgba(10,10,11,0.78) 188px, rgba(10,10,11,0.761) 199px, rgba(10,10,11,0.706) 210px, rgba(10,10,11,0.619) 220px, rgba(10,10,11,0.511) 231px, rgba(10,10,11,0.390) 242px, rgba(10,10,11,0.269) 253px, rgba(10,10,11,0.161) 264px, rgba(10,10,11,0.074) 274px, rgba(10,10,11,0.019) 285px, rgba(10,10,11,0.000) 296px)}
}

/* ---------- brought up to v2b (Michael, 2026-10-04); v2c keeps its fonts and the full-bleed
   story ---------- */
/* On Process heading: eyebrow 8, heading, then 16 to the paragraph */
.story__copy > .t-h2 + *{margin-top:16px}
/* the contact section's eyebrow, 8 above the heading */
.opt .label{margin:0}
.opt .label + .t-h2{margin-top:8px}
/* the form starts on its line: no "Contact" word (the eyebrow says it). set here so the
   v4 port can't bring it back */
.inq .inq__label{display:none}
/* On Process, desktop: with the heading added the copy stands taller (its eyebrow 203-293px
   up, the heading wraps at wide screens), so the treatment's hold now scales with the
   screen: .78 to 140px + 9vw, one eased curve to nothing 108px above. re-measured over every
   photo state at 1280x720, 1440x900, 1920x1080: paragraph 4.67:1 at worst, eyebrow 9.0,
   heading 8.7 (2026-10-04) */
@media (min-width:900px){
  .story--bleed .story__frame::after{background:linear-gradient(to top, rgba(10,10,11,0.78) 0px, rgba(10,10,11,0.78) calc(140px + 9vw), rgba(10,10,11,0.761) calc(140px + 9vw + 10.8px), rgba(10,10,11,0.706) calc(140px + 9vw + 21.6px), rgba(10,10,11,0.619) calc(140px + 9vw + 32.4px), rgba(10,10,11,0.511) calc(140px + 9vw + 43.2px), rgba(10,10,11,0.390) calc(140px + 9vw + 54.0px), rgba(10,10,11,0.269) calc(140px + 9vw + 64.8px), rgba(10,10,11,0.161) calc(140px + 9vw + 75.6px), rgba(10,10,11,0.074) calc(140px + 9vw + 86.4px), rgba(10,10,11,0.019) calc(140px + 9vw + 97.2px), rgba(10,10,11,0.000) calc(140px + 9vw + 108.0px))}
}

/* ================= MOBILE PASS, v2c (Michael, from his phone, 2026-10-05) =================
   phones only; desktop untouched. */
/* On Process, phones: the copy lower in the frame (32 -> 8 from the bottom of the small
   screen height), so more of each photo shows above it and the words sit deeper in the dark
   end of the gradient */
@media (max-width:899px){
  .story--bleed .story__copy{bottom:8px}
}
/* On Process, phones: the treatment behind the copy follows the copy. the copy sits in the
   small screen height (svh) but the photo and its gradient fill the tall one (lvh); when
   Safari's toolbar tucks away the copy rides ~130px up the photo, so every stop is offset by
   (lvh - svh). .78 measured AA but turned the palette grey; dialed back on purpose (Michael,
   2026-10-05): .55, held only up to the bottom of "Materially" (190px above the copy's foot
   on a 393 phone) and gone by just above "On process" (270): the edge dissolves through the
   heading's first line, and the eyebrow sits nearly on the clean photo (it's read over the
   darker frames). over the white palette that is under AA on purpose: paragraph ~2.7:1,
   "Transformed" ~3.8, "Materially" and the eyebrow lower. */
@media (max-width:899px){
  .story--bleed .story__frame::after{background:linear-gradient(to top, rgba(10,10,11,0.605) 0px, rgba(10,10,11,0.605) calc(100lvh - 100svh + 190px), rgba(10,10,11,0.590) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.1), rgba(10,10,11,0.547) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.2), rgba(10,10,11,0.480) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.3), rgba(10,10,11,0.396) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.4), rgba(10,10,11,0.302) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.5), rgba(10,10,11,0.209) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.6), rgba(10,10,11,0.125) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.7), rgba(10,10,11,0.058) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.8), rgba(10,10,11,0.015) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 0.9), rgba(10,10,11,0.000) calc(100lvh - 100svh + 190px + (50% - (100lvh - 100svh + 190px)) * 1.0))}
}

/* v2d (forked from v2c, 2026-10-05): the one difference from v2c.
   phones: while the white palette is up, the words go charcoal and the dark behind them steps
   away, so the palette stays clean white (Michael, 2026-10-05). --pk, set by the story script,
   follows the palette's own fade (0 to 1). dark on the white: ~15:1 for the heading, the
   paragraph's resting charcoal (72%) ~6:1. the thread goes dark too (site.js) */
@media (max-width:899px){
  .story--bleed .story__copy .label, .story--bleed .story__copy .t-h2{
    color:color-mix(in srgb, #141416 calc(var(--pk, 0) * 100%), var(--paper))}
  .story--bleed .story__frame::after{opacity:calc(1 - var(--pk, 0))}
}

/* (Michael, 2026-10-05) 10% darker behind the copy for the raw wood and the weave on phones:
   .55 -> .605. in v2d the palette has no dark behind it anyway (the words go charcoal) */

/* (Michael, 2026-10-05, last pass on this section) the dark behind the copy now ends at half
   the screen: holds to just under "Materially", fades to nothing at 50% up, a purposeful
   cutoff. the palette's push centers on the collection */
@media (max-width:899px){
  .story--bleed .story__img--palette{transform-origin:45% 33%}
}

/* phones: plain line breaking for copy. Safari's text-wrap:pretty re-balances whole paragraphs
   and broke lines early with room to spare (Michael's screenshot: "into", "as"); greedy wrap
   fills each line before breaking (2026-10-05) */
@media (max-width:899px){
  .wall, .t-intro, .caption, .pullquote, .weave-text{text-wrap:wrap}
}

/* phones (Michael, 2026-10-05): a little more room on the right for copy, no hyphenation. text
   now runs to 16px from the right edge (left stays 24: a ragged right reads balanced with a
   slightly narrower margin) */
@media (max-width:899px){
  .band__copy, .band:has(> .band__fig) > .band__copy{padding-right:3px}
  .caption{padding-right:3px}
  .hero__type{right:16px}
  section.opt{padding-right:16px}
  .story--bleed .story__copy{right:16px}
}

/* ===== the rigidity section on phones, copied from v2b (Michael, 2026-10-05): same full bleed,
   pin, eased words and wash; this version's own typeface ===== */
/*    the rigidity section, phones (Michael, 2026-10-05): the photo full bleed, filling the
   screen, pinned. then the words scroll up from the bottom over its right two thirds (the
   cord threading the beads stays clear on the left), lock in place for a few scrolls, and
   the page carries on with both. pure sticky: the image pins at the top; the copy sits in
   the flow right after it, so it rises with the scroll, then pins too; a 60svh spacer at
   the end is the hold. both are a full tall screen (lvh) so they let go together. a
   portrait cut of Adam's full-size export (edges-m.jpg, 1440x2400) puts the cord about 11%
   in from the left. the wash on the image darkens as the copy rises (--q, set by
   "rigidity, phones" in site.js). */
@media (max-width:899px){
  .band--quote{display:block; position:relative; margin-inline:calc(-1 * var(--frame)); height:auto}
  .band--quote::after{content:""; display:block; height:60svh}
  .band--quote .band__media{position:sticky; top:0; z-index:0; height:100vh; height:100lvh;
    aspect-ratio:auto; max-height:none}
  .band--quote .band__media .plate{inset:0}
  .band--quote .plate--edges{background-size:cover; background-position:0% 50%}
  /* the wash: clear over the cord, darkening across the right two thirds, only as dark as
     AA needs (measured at 26px: 4.83:1 at 393, 4.92 at 375, 4.82 at 430; at 30px the
     words count as large text, so AA asks only 3:1) */
  .band--quote .band__media::after{content:""; position:absolute; inset:0; z-index:1;
    pointer-events:none; opacity:var(--q, 0);
    background:linear-gradient(to right, rgba(10,10,11,0) 0%, rgba(10,10,11,0) calc(24% + 30px),
      rgba(10,10,11,.36) calc(36% + 30px), rgba(10,10,11,.53) calc(52% + 30px), rgba(10,10,11,.53) 100%)}
  /* (Michael, 2026-10-05) the photo moved 30px right so the cord lines up with the second A
     of the name (edges-m.jpg re-cut 85px wider on the left); the wash moved with it */
  /* (darkened behind the words so they pop, Michael 2026-10-05: .42 -> .48 -> .53; the
     cord's side stays fully clear) */
  .band--quote .band__copy{position:sticky; top:0; z-index:1; height:100vh; height:100lvh;
    margin:0; box-sizing:border-box; display:flex; flex-direction:column; justify-content:center;
    padding:64px calc(var(--frame) + var(--pad)) 0 33.333vw}
  /* right-aligned, ragged left (Michael, 2026-10-05): the lines end on the page's right rail
     (24px, the same edge as the top bar's v2c), not against the glass, where italics clip.
     64 at the top so the words center in the space below the top bar (44px) */
  /* the words: 27 (30 read a touch big), condensed, the left margin a third in */
  .band--quote .pullquote{font-size:27px; line-height:1.15; opacity:1; transform:none; transition:none;
    text-align:right}
}

/* the rigidity sequence, eased (Michael, 2026-10-05), where the browser can link animation
   to scroll (it runs on the compositor, so it doesn't stutter on iOS the way script-moved
   images do). measured in screens (lvh) of scroll past the moment the section's top meets
   the top of the screen (u):
     -20..20  the photo eases into its lock: it slows to a stop instead of halting
      45..135 the words rise from just below the fold at scroll speed, easing into place
     135..185 they hold
     185..275 they ease out of place and scroll up and away
     275..298 the photo alone again, the same beat as before the words came
     298..338 the photo eases out of its lock and the page carries on
   ranges are percentages of the 'cover' range (section 418lvh + one screen = 518lvh;
   x = u + 100): Safari ignored them written in lvh, which broke it there (2026-10-05).
   it only switches on (html.rig-sda) once the script has confirmed the browser attached the
   animations to the scroll; anywhere else the plain sticky version above stands. */
@media (max-width:899px){
    html.rig-sda .band--quote{view-timeline:--rig block}
    html.rig-sda .band--quote::after{height:318lvh}
    html.rig-sda .band--quote .band__media{
      animation:rig-img-in linear both, rig-img-out linear both;
      animation-timeline:--rig, --rig;
      animation-range:cover 15.444% cover 23.166%, cover 76.834% cover 84.556%}
    html.rig-sda .band--quote .band__media::after{
      animation:rig-wash linear both; animation-timeline:--rig;
      animation-range:cover 27.992% cover 72.394%}
    html.rig-sda .band--quote .band__copy{margin-top:-100vh; margin-top:-100lvh;
      animation:rig-text-in linear both, rig-text-out linear both;
      animation-timeline:--rig, --rig;
      animation-range:cover 27.992% cover 45.367%, cover 55.019% cover 72.394%}
}
/* the photo's lock, eased: offsets from plain sticky. in: it slows to rest over 40lvh of
   scroll (quadratic, starting at scroll speed); out: the mirror */
@keyframes rig-img-in{
  0%{translate:0 0} 12.5%{translate:0 .312lvh} 25%{translate:0 1.25lvh} 37.5%{translate:0 2.812lvh}
  50%{translate:0 5lvh} 62.5%{translate:0 2.812lvh} 75%{translate:0 1.25lvh} 87.5%{translate:0 .312lvh}
  100%{translate:0 0}}
@keyframes rig-img-out{
  0%{transform:translateY(0)} 12.5%{transform:translateY(-.312lvh)} 25%{transform:translateY(-1.25lvh)}
  37.5%{transform:translateY(-2.812lvh)} 50%{transform:translateY(-5lvh)} 62.5%{transform:translateY(-2.812lvh)}
  75%{transform:translateY(-1.25lvh)} 87.5%{transform:translateY(-.312lvh)} 100%{transform:translateY(0)}}
/* the words: at scroll speed, then easing to rest (quadratic); leaving, the mirror */
@keyframes rig-text-in{
  0%{translate:0 70lvh; animation-timing-function:linear}
  55.556%{translate:0 20lvh; animation-timing-function:cubic-bezier(.333,.667,.667,1)}
  100%{translate:0 0}}
@keyframes rig-text-out{
  0%{transform:translateY(0); animation-timing-function:cubic-bezier(.333,0,.667,.333)}
  44.444%{transform:translateY(-20lvh); animation-timing-function:linear}
  100%{transform:translateY(-70lvh)}}
/* the wash comes in with the words and goes with them */
@keyframes rig-wash{0%{opacity:0} 21.7%{opacity:1} 78.3%{opacity:1} 100%{opacity:0}}

/* phones: the rigidity quote keeps its earlier, better line breaking (pretty), even though
   the rest of the copy now wraps plainly (Michael, 2026-10-05) */
@media (max-width:899px){
  .band--quote .pullquote{text-wrap:pretty}
}

/* the form (Michael, 2026-10-05): no labels on the fields. each field shows its name as a
   ghosted placeholder inside it (set from the label by site.js) that clears as you type, to
   win back vertical space on desktop and phones. the label stays for screen readers, hidden
   from view */
.inq .inq-field > .inq-field__label{position:absolute !important; width:1px; height:1px; margin:0; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; top:auto; transform:none}
.inq .inq-field > .inq-field__box{margin-top:0; padding-top:0}
.inq .inq-field input::placeholder, .inq .inq-field textarea::placeholder{color:rgba(236,231,223,.5); opacity:1}
.inq .inq-field input:focus::placeholder, .inq .inq-field textarea:focus::placeholder{color:rgba(236,231,223,.32)}
