/* adamwier.studio stopgap. Built from Booker T (prototype v5) on 2026-09-29; standalone from here on. */
/* ============================================================
   beads — shared core
   tokens, page load, type scale, fades, form, footer
   ============================================================ */

:root{
  --ink:#0a0a0b;
  --ink-2:#121214;
  --paper:#e9e5df;
  --paper-dim:#cfc9c1;   /* secondary copy — light enough to hold over photography */
  --rule:rgba(233,229,223,.12);
  --olive:#8a853a;          /* accent, off the bead palette */
  --gutter:clamp(22px,5vw,80px);
  --frame:13px;                /* the catalogue border */
  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; overflow-x:clip}
body{
  margin:0; background:var(--ink); color:var(--paper);
  font-family:"Helvetica Neue",Helvetica,Inter,system-ui,-apple-system,sans-serif;
  font-weight:300; -webkit-font-smoothing:antialiased; overflow-x:clip;
}

/* ---------- page load: the v2/v4 plush veil ---------- */
.veil{
  position:fixed; inset:0; background:var(--ink); z-index:99;
  pointer-events:none; opacity:1; transition:opacity 1800ms var(--ease);
}
body.ready .veil{opacity:0}

.mark{
  position:fixed; top:clamp(22px,3.4vh,40px); left:calc(var(--gutter) + var(--frame));
  z-index:20; opacity:0; transition:opacity 1600ms var(--ease) 700ms; mix-blend-mode:difference;
}
body.ready .mark{opacity:1}

/* ---------- type ---------- */
.label{
  font-size:clamp(10px,.72vw,12px); letter-spacing:.22em; text-transform:uppercase;
  color:var(--paper-dim); font-weight:500; margin:0;
}
.lede{
  font-size:clamp(22px,2.35vw,38px); line-height:1.32; font-weight:300;
  letter-spacing:-.01em; margin:0;
}
.wall{
  font-size:clamp(15px,1.1vw,18px); line-height:1.75; color:var(--paper-dim);
  max-width:40ch; font-weight:400; margin:0;
}
.wall em{color:var(--paper); font-style:italic}
.stack{display:flex; flex-direction:column; gap:clamp(14px,2vh,24px)}

/* the opening line, set to break as:
     Three thousand two hundred forty-nine
     painted wooden beads, hand-woven into
     a single plane.
   measured in em so it holds at every step of the type scale */
.lede--hero{max-width:17.7em}

/* ---------- reveal ---------- */
.rise{
  opacity:0; transform:translate3d(0,30px,0);
  transition:opacity 1600ms var(--ease-out), transform 1600ms var(--ease-out);
}
.rise.in{opacity:1; transform:none}
.rise[data-d="1"]{transition-delay:360ms}
.rise[data-d="2"]{transition-delay:720ms}
.rise[data-d="3"]{transition-delay:1080ms}

/* ---------- blur-up plates ---------- */
.plate{
  position:absolute; inset:0; background-size:cover; background-position:center;
  filter:blur(22px); transition:filter 1700ms var(--ease); will-change:transform;
}
.plate.loaded{filter:blur(0)}

/* ---------- inquiry + footer ---------- */
.inquire{
  padding:clamp(110px,18vh,190px) calc(var(--gutter) + var(--frame)) clamp(60px,10vh,110px);
  max-width:1760px; margin-inline:auto;
  display:grid; gap:clamp(36px,5vw,90px); grid-template-columns:1fr;
}
@media (min-width:900px){.inquire{grid-template-columns:minmax(0,.85fr) minmax(0,1fr)}}
form{display:flex;flex-direction:column;gap:30px;max-width:560px}
fieldset{border:0;margin:0 0 14px;padding:0;display:flex;flex-direction:column;gap:18px}
legend{padding:0;margin-bottom:16px}
.choices{display:flex;flex-wrap:wrap;gap:12px;margin-top:20px}
.choice{position:relative}
.choice input{position:absolute;opacity:0;width:0;height:0}
.choice span{
  display:inline-block;padding:11px 18px;border:1px solid var(--rule);border-radius:999px;
  font-size:14px;color:var(--paper-dim);cursor:pointer;
  transition:color .4s var(--ease),border-color .4s var(--ease),background .4s var(--ease);
}
.choice span:hover{color:var(--paper);border-color:var(--paper-dim)}
.choice input:checked + span{color:var(--ink);background:var(--paper);border-color:var(--paper)}
.choice input:checked + span:hover{background:var(--olive);border-color:var(--olive)}
.choice input:focus-visible + span{outline:2px solid var(--paper);outline-offset:3px}
.field{display:flex;flex-direction:column;gap:11px}
input[type=text],input[type=email],textarea{
  background:transparent;border:0;border-bottom:1px solid var(--rule);color:var(--paper);
  font:inherit;font-size:16px;padding:10px 0;border-radius:0;transition:border-color .5s var(--ease);
}
input:focus,textarea:focus{outline:0;border-bottom-color:var(--paper)}
textarea{resize:vertical;min-height:96px}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
button{
  align-self:flex-start;margin-top:8px;background:transparent;color:var(--paper);
  border:1px solid var(--rule);border-radius:999px;padding:14px 30px;font:inherit;
  font-size:14px;letter-spacing:.06em;cursor:pointer;
  transition:background .5s var(--ease),color .5s var(--ease),border-color .5s var(--ease);
}
button:hover{background:var(--olive);color:var(--ink);border-color:var(--olive)}
footer{
  padding:28px calc(var(--gutter) + var(--frame)) 46px; max-width:1760px; margin-inline:auto;
  display:flex;flex-wrap:wrap;gap:16px 34px;justify-content:space-between;
}
footer a{color:var(--paper-dim);text-decoration:none}
footer a:hover{color:var(--paper)}


@media (prefers-reduced-motion:reduce){
  *{transition-duration:1ms !important; animation:none !important}
  .rise{opacity:1;transform:none}
}

/* detail-160's subject sits hard left — copy shown with it moves right
   so the cord and knot stay uncovered */
.copy-right{left:auto !important; right:calc(var(--gutter) + var(--frame)) !important;
            margin-left:auto !important; text-align:left}
@media (max-width:899px){
  .copy-right{left:var(--gutter) !important; right:var(--gutter) !important}
}

/* ---------- fitting the box to the words --------------------
   treatments (halo, cylindrical light) are drawn to the copy
   block, so a block sitting at its max-width while the longest
   line falls short shows shade where no text lives.
   fit-content shrinks the box to the longest rendered line;
   text-wrap evens the rag so the remaining gaps stay small. */
.stack, .col, .band__copy, .hero__type, .lab__type, .plate__cap,
.drift__type, .scan__type, .grade__type, .offset{
  width:fit-content; max-width:100%;
}
/* no balance on .lede — it re-breaks the hero's measured line structure */
.wall{text-wrap:pretty}
/* right-hung copy still needs to sit against the right edge */
.copy-right, .col--right{margin-left:auto}

/* body copy fills its block — the block is already measured by
   fit-content, so a second cap on .wall just left a gap on the right */
.stack > .wall, .col .wall, .band__copy .wall{max-width:none}
/* ============================================================
   beads — surface treatments
   ============================================================ */

/* ---------- HALO -------------------------------------------
   legibility from the letterforms. no container, no edge.
   the shade sits in its own layer BEHIND the words, always.   */
.fx-halo{position:relative; isolation:isolate; --halo:.70; --halo-x:42%; --halo-y:64%}
.fx-halo > *{position:relative; z-index:2}
.fx-halo::before{
  content:""; position:absolute; z-index:-1; pointer-events:none;
  /* z-index:-1 inside the isolated context paints behind the element's
     own text, so this works whether .fx-halo is on a wrapper or on the
     paragraph itself. symmetric insets + a centred gradient keep the
     shade behind the block rather than off its left edge. */
  inset:calc(-1 * var(--halo-y)) calc(-1 * var(--halo-x));
  background:radial-gradient(closest-side ellipse at 50% 50%,
             rgba(6,6,7,var(--halo)) 0%,
             rgba(6,6,7,calc(var(--halo) * .6)) 44%,
             rgba(6,6,7,0) 78%);
}
.fx-halo .lede,
.fx-halo .wall,
.fx-halo .label,
.lede.fx-halo,.wall.fx-halo,.label.fx-halo{
  text-shadow:
    0 0 14px rgba(6,6,7,.92),
    0 0 34px rgba(6,6,7,.78),
    0 0 70px rgba(6,6,7,.62),
    0 1px 2px rgba(6,6,7,.9);
}

/* ---------- CYLINDRICAL LIGHT ------------------------------
   the rows read as tubes. pool shade between them so the page
   picks up the same corduroy the object has.                  */
.fx-cyl{
  position:relative; isolation:isolate;
  /* how far the effect's box spreads past the copy, per side.
     the box ends up 100% + 2x these. these are chosen so the spread
     lands at a similar number of pixels on both axes, since the copy
     blocks are far wider than they are tall. */
  --spread-x:38%;
  --spread-y:70%;
  /* peak darkness of a band. the trough and the shoulder are struck
     from it, so one number moves the whole rhythm. */
  --band:.94;
  /* how far the field holds before the perimeter dissolves */
  --fade:54%;
}
.fx-cyl--dim{--band:.84}
.fx-cyl--soft{--band:.73}
.fx-cyl--bare{--band:.012}
.fx-cyl > *{position:relative; z-index:2}
.fx-cyl::before{
  content:""; position:absolute; z-index:1; pointer-events:none;
  /* the pseudo's own box — nothing here touches the copy's space */
  inset:calc(-1 * var(--spread-y)) calc(-1 * var(--spread-x));
  background-image:repeating-linear-gradient(
      to bottom,
      rgba(6,6,7,var(--band)) 0px, rgba(6,6,7,var(--band)) 3px,
      rgba(6,6,7,calc(var(--band) * .66)) 7px,
      rgba(6,6,7,calc(var(--band) * .91)) 12px,
      rgba(6,6,7,var(--band)) 16px);
  /* a centred ellipse with an eased falloff, so the perimeter dissolves
     rather than ramping to a visible edge */
  -webkit-mask-image:radial-gradient(ellipse var(--fade) calc(var(--fade) - 2%) at 50% 50%,
      rgba(0,0,0,1) 5%, rgba(0,0,0,.70) 30%, rgba(0,0,0,.30) 55%,
      rgba(0,0,0,.08) 75%, transparent 95%);
  mask-image:radial-gradient(ellipse var(--fade) calc(var(--fade) - 2%) at 50% 50%,
      rgba(0,0,0,1) 5%, rgba(0,0,0,.70) 30%, rgba(0,0,0,.30) 55%,
      rgba(0,0,0,.08) 75%, transparent 95%);
}



/* ============================================================
   GLASS
   frost that is not a panel behind text
   ============================================================ */

/* --- glass as horizon ----------------------------------
   the lower part of the frame frosts over a long falloff.
   atmosphere rather than a container.                        */
.fx-glass-horizon{
  position:absolute; left:0; right:0; bottom:0; height:62%;
  pointer-events:none; z-index:2;
  background:linear-gradient(to bottom, rgba(255,255,255,.02), rgba(255,255,255,.15));
  -webkit-backdrop-filter:blur(22px) saturate(1.22);
  backdrop-filter:blur(22px) saturate(1.22);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.35) 26%, #000 72%);
  mask-image:linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.35) 26%, #000 72%);
}

/* ---------- TRAVELLING LIGHT -------------------------------
   one slow source crossing the page. the object never moves;
   the light does.                                             */
.sweep{
  position:fixed; inset:0; z-index:6; pointer-events:none;
  mix-blend-mode:soft-light; opacity:.85;
  background:
    radial-gradient(ellipse 58% 44% at 18% 8%, rgba(255,246,228,.34) 0%, rgba(255,246,228,0) 64%),
    radial-gradient(ellipse 70% 60% at 86% 92%, rgba(90,110,150,.22) 0%, rgba(90,110,150,0) 62%);
  animation:daylight 190s var(--ease) infinite alternate;
}
@keyframes daylight{
  0%  {background-position: 0% 0%,  100% 100%; filter:hue-rotate(0deg)  brightness(1)}
  50% {background-position: 46% 18%, 58% 78%;  filter:hue-rotate(-6deg) brightness(1.06)}
  100%{background-position: 92% 34%, 14% 58%;  filter:hue-rotate(5deg)  brightness(.95)}
}
.sweep--spec{
  mix-blend-mode:overlay; opacity:.30; animation-duration:74s;
  background:linear-gradient(104deg,
    rgba(255,255,255,0) 34%, rgba(255,255,255,.34) 50%, rgba(255,255,255,0) 66%);
  background-size:260% 260%;
}

@media (prefers-reduced-motion:reduce){
  .sweep{animation:none}
}
body{background:var(--ink-2)}
/* one left rail: the wordmark, the hero line and every copy block
   share it, so nothing shifts sideways as you scroll */
:root{--rail:calc(var(--frame) + clamp(30px,4vw,68px))}
.mark{left:var(--rail)}
/* full-bleed hero, then everything below is framed */
.hero{position:relative; height:100svh; overflow:visible}
/* the hero picture is pinned to the screen and the rest of the page
   scrolls up over it. the section still reserves its 100svh, so
   nothing below moves. */
.hero .plate{position:fixed; inset:-12% 0; z-index:0}
/* an even grade over the whole hero, under the copy. it rides with the
   picture, so the two stay together while the copy scrolls away. */
/* off 2026-10-02: hero shown as shot
.hero::after{
  content:""; position:fixed; inset:0; z-index:1; pointer-events:none;
  background:rgba(10,10,11,.32);
}
*/
/* everything after the hero is the cover: without its own surface the
   pinned picture shows through the gaps between bands */
.sheet, .opt, footer{position:relative; z-index:2; background:var(--ink-2)}
/* an even grade over the whole hero, under the copy */
/* off 2026-10-02: hero shown as shot
.hero::after{
  content:""; position:absolute; inset:0; z-index:2; pointer-events:none;
  background:rgba(10,10,11,.32);
}
*/
.hero .plate{inset:-12% 0}
/* v3.2's hero treatment: the row banding, at that page's hero values */
.hero__type{--spread-x:48%; --spread-y:57%; --band:.93; --fade:54%}
/* the hero line sits in the right third, centred vertically */
.hero__type{
  position:absolute; z-index:3; left:auto;
  right:calc(var(--gutter) + 100px); top:50%; transform:translateY(-50%);
  width:min(620px,52vw);
}
/* flow-root: without it the first band's top margin collapses out of
   the sheet, so its background starts below the gap and the pinned
   hero shows through as a strip */
.sheet{padding:0 var(--frame) var(--frame); display:flow-root}
.band{
  /* the gap between bands is the frame, four times over: still the
     same system, with room to breathe */
  /* the same surface as the page behind it. the deeper --ink made the
     bands read as cards mounted on a different material. --ink-2 is
     the matte of the two. */
  position:relative; background:var(--ink-2); margin-top:calc(var(--frame) * 8);
  display:grid; grid-template-columns:1fr; align-items:stretch;
  /* one height for every band, so the page has a rhythm rather than
     three different rules producing three different sizes */
  min-height:84svh;
}
.band__media{position:relative; overflow:hidden; min-height:46svh}
.band__media .plate{inset:-10% 0}
.band__copy{
  display:flex; flex-direction:column; justify-content:center; gap:24px;
  padding:clamp(72px,11vh,140px) clamp(38px,5vw,84px);
}
@media (min-width:900px){
  .band--split{grid-template-columns:minmax(0,1.45fr) minmax(0,1fr)}
  .band--split.band--flip{grid-template-columns:minmax(0,1fr) minmax(0,1.45fr)}
  .band--split.band--flip .band__media{order:2}
  .band--tall .band__media{min-height:0}
}
.band--full .band__media{min-height:0}
/* a graded wash of black over the closing picture */
.band--full .band__media::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(10,10,11,0) 0%, rgba(10,10,11,.18) 42%,
    rgba(10,10,11,.52) 76%, rgba(10,10,11,.78) 100%);
}
.band--full .band__copy{z-index:2}
.band--full .band__copy{
  position:absolute; inset:0; z-index:2;
  display:flex; align-items:center; justify-content:center;
  /* core.css gives .band__copy width:fit-content, which shrinks this
     box away from the frame it is supposed to fill */
  width:auto; max-width:none; padding:0; text-align:center;
}
.band--full .band__copy .lede{margin:0; max-width:31ch}
@media (max-width:899px){
  .band--full .band__copy{max-width:none; position:static}
  .hero__type{max-width:none}
}
/* 200px off the space above the footer copy, and nothing off the
   bottom: the section is sized directly rather than centred, so the
   two gaps are set independently. */
section.opt{
  min-height:0; align-items:flex-start;
  padding-top:214px; padding-bottom:315px;
}
/* ---------- phones and small tablets ----------
   the pictures carry the page, so they get the height; copy is set
   close under each one instead of floating in a padded box */
@media (max-width:899px){
  .hero__type{
    left:var(--gutter); right:var(--gutter); top:auto; transform:none;
    bottom:clamp(56px,11svh,110px); width:auto;
  }
  .hero__type .lede--hero{font-size:clamp(24px,6.6vw,32px)}
  .band{min-height:0; margin-top:calc(var(--frame) * 4)}
  .band__media{min-height:64svh}
  .band__copy{padding:40px calc(var(--gutter) - var(--frame)) 52px; gap:18px}
  /* the closer keeps its words on the picture, low, in the dark of the wash */
  .band--full .band__media{min-height:80svh}
  .band--full .band__copy{
    position:absolute; inset:auto 0 0 0; align-items:flex-end; justify-content:flex-start;
    padding:0 calc(var(--gutter) - var(--frame)) 44px; text-align:left;
  }
  section.opt{padding-top:96px; padding-bottom:120px}
}

@media (min-width:900px){
  .hero__type{
    left:calc(var(--gutter) + var(--frame)); right:auto;
    top:auto; bottom:clamp(70px,16vh,180px); transform:none;
    width:auto; max-width:min(760px,52vw);
  }
  .mark{left:calc(var(--gutter) + var(--frame))}
}
.opt{
  min-height:100svh; display:flex; align-items:center;
  padding:clamp(80px,12vh,150px) calc(var(--gutter) + var(--frame, 0px));
  border-bottom:1px solid rgba(233,229,223,.10);
}
.opt__inner{
  width:100%; max-width:1760px; margin-inline:auto;
  display:grid; gap:clamp(36px,5vw,90px); grid-template-columns:1fr;
}
@media (min-width:900px){ .opt__inner{grid-template-columns:minmax(0,.9fr) minmax(0,1fr)} }
.opt__num{color:var(--paper-dim); margin-bottom:22px}
/* one measure for the whole copy column, in rem so the heading and the
   paragraph fill the same width instead of each finding its own. no
   balancing: balance broke the heading early and left the paragraph
   running 200px further, which is what read as ragged. */
.opt__inner > div{max-width:34rem}
.opt .lede{max-width:none; text-wrap:normal; margin-bottom:22px}
.opt .wall{max-width:none}

/* choosing is not the same job as sending, so it does not look like the
   send button: a plain radio list. */
.radios{display:flex; flex-direction:column; gap:16px; margin-top:22px}
.radio{display:flex; align-items:center; gap:13px; cursor:pointer; font-size:15px}
.radio input{position:absolute; opacity:0; width:0; height:0}
.radio i{
  width:15px; height:15px; border-radius:50%; border:1px solid var(--rule);
  flex:none; position:relative; transition:border-color .3s var(--ease);
}
.radio i::after{
  content:""; position:absolute; inset:3px; border-radius:50%;
  background:var(--olive); transform:scale(0); transition:transform .3s var(--ease);
}
.radio:hover i{border-color:var(--paper-dim)}
.radio input:checked + i{border-color:var(--olive)}
.radio input:checked + i::after{transform:scale(1)}
.radio input:focus-visible + i{outline:2px solid var(--paper); outline-offset:3px}

.link{
  background:none; border:0; border-radius:0; padding:0; margin:0; align-self:auto;
  font:inherit; font-size:15px; letter-spacing:0; cursor:pointer;
  color:var(--paper); text-decoration:none; border-bottom:1px solid var(--rule);
  transition:border-color .35s var(--ease), color .35s var(--ease);
}
.link:hover{background:none; color:var(--paper); border-bottom-color:var(--paper)}

/* start over: a quiet text link with the conventional reset glyph */
.link--reset{
  display:inline-flex; align-items:center; gap:8px;
  border-bottom:0; color:var(--paper-dim); font-size:14px;
  transition:color .35s var(--ease);
}
.link--reset svg{width:14px; height:14px; flex:none; transition:transform .5s var(--ease)}
.link--reset span{border-bottom:1px solid var(--rule); transition:border-color .35s var(--ease)}
.link--reset:hover{background:none; color:var(--paper)}
.link--reset:hover span{border-bottom-color:var(--paper)}
.link--reset:hover svg{transform:rotate(-120deg)}
.link--reset:focus-visible{outline:2px solid var(--paper); outline-offset:4px}
/* the appointment link is the live thing once available work is chosen */
.branch.on .link{color:var(--olive); border-bottom-color:rgba(138,133,58,.5)}
.branch.on .link:hover{border-bottom-color:var(--olive)}
/* the trail and its undo share a line: start over belongs to the
   crumbs, not to the question below them, so it stays out of the
   vertical run of trail -> question -> answer */
/* the questions stay at the top of the column so the thing you click is
   always in the same place. the answers collect underneath. */
.trail{position:relative; margin:34px 0 28px}
/* the crumbs grow and wrap; the undo does not move with them. it is
   pinned to the top right of the trail, level with the first row, so
   it stays in one place for the whole flow. */
.trail .crumbs{margin-bottom:0; padding-right:124px}
/* quieter than an answer, and it arrives on its own clock so it reads
   as a different kind of thing */
.trail .link--reset{
  position:absolute; right:0; top:9px;
  font-size:12px; color:var(--paper-dim); opacity:0;
  transition:opacity 1400ms var(--ease) 600ms, color .35s var(--ease);
}
.trail:not([hidden]) .link--reset{opacity:.62}
.trail .link--reset:hover{opacity:1; color:var(--paper)}
.trail .link--reset svg{width:12px; height:12px}
@media (max-width:560px){
  .trail .crumbs{padding-right:0}
  .trail .link--reset{position:static; margin-top:16px}
}
.opt form{margin:0}
/* progressive questions: each answered step stays visible above the next */
.step{
  opacity:0; max-height:0; overflow:hidden; pointer-events:none;
  transition:opacity 700ms var(--ease-out), max-height 700ms var(--ease-out);
}
.step.on{opacity:1; max-height:320px; pointer-events:auto}
.step .label{display:block; margin-bottom:16px}
.answered{display:flex; flex-wrap:wrap; gap:10px; align-items:baseline}
.answered .label{margin:0}
.answered b{font-weight:400; color:var(--paper)}
.ref{color:var(--paper-dim); font-size:13px; margin-top:10px; display:none}
.ref.on{display:block}
.step:not([data-step="hang"]) .ref{display:block}

/* answered questions collapse to a line of crumbs you can click back into */
.crumbs{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:28px}
.crumb{
  display:inline-flex; align-items:center; gap:9px;
  border:1px solid var(--rule); border-radius:999px; padding:7px 14px;
  font-size:13px; color:var(--paper); background:transparent; cursor:pointer;
  transition:border-color .35s var(--ease), color .35s var(--ease);
}
.crumb:hover{border-color:var(--olive)}
.crumb:hover span{color:var(--olive)}
.crumb span{color:var(--paper-dim); font-size:10px; letter-spacing:.18em; text-transform:uppercase}
.crumb b{font-weight:400}
.step{display:none}
.step.on{display:block}
.step .label{display:block; margin-bottom:16px}
.branch{display:none; margin-bottom:26px}
.branch.on{display:block}
.branch .wall + .field, .branch p + .field{margin-top:26px}

/* two ways in: a segmented control rather than a radio list. both
   choices stay on screen, so nothing is hidden behind a selection.
   it is a div, not a fieldset: chrome lays fieldset contents out in an
   anonymous box and the absolutely positioned indicator inside one
   ignores percentage transforms. */
.seg{
  position:relative; display:grid; grid-template-columns:1fr 1fr;
  border:1px solid var(--rule); border-radius:999px; padding:0; margin:0 0 34px;
  overflow:hidden;
}
.seg__lede{margin:0 0 14px}
.seg__ind{
  position:absolute; inset:0 50% 0 0; background:var(--olive);
  /* square ends: the track's own radius and overflow clip the outer
     end into the pill, and the centre stays flat in either state. */
  border-radius:0;
  transition:transform .42s var(--ease);
}
.seg:has(.seg__opt:last-of-type input:checked) .seg__ind{transform:translateX(100%)}
.seg__opt{
  position:relative; z-index:1; display:flex; align-items:center; justify-content:center;
  text-align:center; padding:19px 20px; cursor:pointer; font-size:16px;
  color:var(--paper-dim); transition:color .42s var(--ease);
}
.seg__opt input{position:absolute; opacity:0; width:0; height:0}
.seg__opt:has(input:checked){color:var(--ink)}
.seg__opt:has(input:focus-visible){outline:2px solid var(--paper); outline-offset:3px}
@media (max-width:560px){ .seg__opt{font-size:14px; padding:16px 12px} }

/* the outer box never moves; only the contents cross over, so the
   footer below it does not lurch. */
.panes{position:relative; display:grid}
.pane{
  grid-area:1 / 1; display:flex; flex-direction:column; gap:26px;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .38s var(--ease), visibility .38s;
}
.pane.on{opacity:1; visibility:visible; pointer-events:auto}
.sketch{color:var(--paper-dim); opacity:.65; margin-top:6px}
.branch .field{display:flex; flex-direction:column; gap:11px}
.tailfields{display:none; flex-direction:column; gap:26px}
.tailfields.on{display:flex}

/* ---------- live form: sending, sent, and a failure that says what to do ---------- */
.cf-turnstile{min-height:0}
.status{font-size:14px; color:var(--paper-dim); min-height:1.5em; margin:0}
.flow.sending button[type=submit]{opacity:.5; pointer-events:none}
.thanks{display:none}
.thanks .lede{margin-bottom:22px}
.flow.sent{display:none}
.flow.sent + .thanks{display:block}

/* ---------- Adam's copy and photos, 2026-10-02 ---------- */

/* the hero's sharp beads sit right of centre; keep them in a portrait crop */
.hero .plate{background-position:70% 50%}

/* the weave: the cord edge sits left of centre */
.plate--edges{background-position:30% 50%}

/* on process: two pictures side by side, the paragraph beneath on the rail */
.band--pair{display:block; min-height:0}
.pair{display:grid; grid-template-columns:1fr 1fr; gap:var(--frame)}
.pair .band__media{min-height:clamp(320px,64svh,860px)}
.band--pair .band__copy{padding-top:clamp(48px,8vh,96px); padding-bottom:clamp(48px,8vh,96px)}
.band--pair .band__copy .wall{max-width:46ch}
@media (max-width:899px){
  .pair{grid-template-columns:1fr}
  .pair .band__media{min-height:52svh}
  .band--pair .band__copy{padding:40px calc(var(--gutter) - var(--frame)) 52px}
}

/* the palette is shot on white. a dark falloff at the edges so it sits in
   the page instead of glaring out of it */
.band__media--palette::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:radial-gradient(ellipse 75% 70% at 50% 50%,
    rgba(18,18,20,0) 40%, rgba(18,18,20,.35) 75%, rgba(18,18,20,.75) 100%),
    rgba(18,18,20,.12);
}

/* the hero copy arrives with the page, not on scroll: on phones its last
   line sits below the reveal trigger and would otherwise never show */
body.ready .hero .rise{opacity:1; transform:none}

/* ---------- top bar: a fade from the top edge, the name left, Contact right.
   fixed, so Contact is one tap away at every scroll position. replaces the
   difference-blended .mark, which got hard to read over the brighter hero. ---------- */
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){ html{scroll-behavior:auto} }
.top{
  position:fixed; top:0; left:0; right:0; z-index:20; pointer-events:none;
  display:flex; justify-content:space-between; align-items:baseline;
  padding:clamp(22px,3.4vh,40px) var(--rail) 0;
  opacity:0; transition:opacity 1600ms var(--ease) 700ms;
}
body.ready .top{opacity:1}
.top::before{
  content:""; position:absolute; left:0; right:0; top:0; z-index:-1;
  height:calc(100% + clamp(70px,9vh,120px));
  background:linear-gradient(to bottom,
    rgba(18,18,20,.72) 0%, rgba(18,18,20,.46) 40%,
    rgba(18,18,20,.16) 75%, rgba(18,18,20,0) 100%);
}
.top .label{color:var(--paper)}
.top__link{
  pointer-events:auto; text-decoration:none;
  border-bottom:1px solid transparent; padding-bottom:3px;
  transition:border-color .35s var(--ease), color .35s var(--ease);
}
.top__link:hover{border-bottom-color:var(--paper)}
.top__link:focus-visible{outline:2px solid var(--paper); outline-offset:4px}
@media (min-width:900px){
  .top{padding-left:calc(var(--gutter) + var(--frame)); padding-right:calc(var(--gutter) + var(--frame))}
}

/* ============================================================
   TYPE SYSTEM, 2026-10-02
   one role, one look. roughly a 1.33 scale on desktop, tighter on
   phones. uppercase with tracking is reserved for the section
   eyebrow (.label) and nothing else.
     h1      hero title            64 / 36   light
     h2      section heading       40 / 28   light
     intro   the line under h1     23 / 18   regular, full white
     body    paragraphs            18 / 16   regular, dim  (.wall)
     eyebrow section label         12        medium, caps  (.label)
     meta    location, notes, ©    14 / 13   regular, dim
     name    top left              16        medium
     nav     Contact               14        regular
     form    questions, fields     15        medium
   ============================================================ */
.t-h1{
  font-size:clamp(36px,4.45vw,64px); line-height:1.08; font-weight:300;
  letter-spacing:-.02em; margin:0;
}
.t-h2{
  font-size:clamp(28px,2.8vw,40px); line-height:1.18; font-weight:300;
  letter-spacing:-.015em; margin:0;
}
.t-intro{
  font-size:clamp(18px,1.6vw,23px); line-height:1.45; font-weight:400;
  color:var(--paper); margin:0; max-width:34ch; text-wrap:pretty;
}
.wall{font-size:clamp(16px,1.25vw,18px); line-height:1.7}
.label{font-size:12px; letter-spacing:.22em; font-weight:500}
.t-meta{
  font-size:clamp(13px,.98vw,14px); line-height:1.5; font-weight:400;
  letter-spacing:.01em; color:var(--paper-dim); margin:0;
}
.t-name{font-size:16px; font-weight:500; letter-spacing:.01em; color:var(--paper)}
.t-nav{font-size:14px; font-weight:400; letter-spacing:.02em; color:var(--paper)}
.t-form{
  display:block; font-size:15px; font-weight:500; letter-spacing:0;
  color:var(--paper); margin:0;
}
.step .t-form{margin-bottom:16px}
.seg__lede{margin:0 0 16px}
.opt .t-h2{margin-bottom:22px}
.thanks .t-h2{margin-bottom:22px}
.ref.t-meta{font-size:13px}
/* the hero stack spaces title, intro and meta apart a little more */
.hero__type{gap:clamp(16px,2.2vh,26px)}
.hero__type .t-meta{margin-top:4px}
/* section copy: eyebrow, heading, body */
.band__copy .t-h2{margin:0}
/* answer chips: the question in meta style rather than tiny caps */
.crumb span{font-size:12px; letter-spacing:0; text-transform:none}

/* ---------- the wall label (museum tombstone) ----------
   a small card mounted on the photo's lower corner, the way a label
   hangs beside a piece. warm paper, charcoal type: it reads as an
   object, not as more page copy. title in italics, then year,
   materials, size, and availability set apart. */
.tag{
  position:absolute; z-index:3; left:clamp(16px,2.2vw,32px); bottom:clamp(16px,2.2vw,32px);
  width:min(300px, calc(100% - 32px));
  background:#e9e5df; color:#1d1c1a;
  padding:18px 20px 16px;
  box-shadow:0 1px 2px rgba(0,0,0,.18), 0 8px 24px rgba(0,0,0,.22);
}
.tag p{margin:0}
.tag__title{font-size:15px; line-height:1.35; font-weight:500}
.tag__sub{font-size:13px; line-height:1.4; color:#4a4743; margin-top:3px !important}
.tag__meta{font-size:13px; line-height:1.55; color:#4a4743; margin-top:12px !important}
.tag__avail{
  font-size:13px; line-height:1.4; color:#1d1c1a; margin-top:12px !important;
  padding-top:10px; border-top:1px solid rgba(29,28,26,.16);
}
@media (max-width:899px){
  .tag{width:min(260px, calc(100% - 32px)); padding:14px 16px 12px}
  .tag__title{font-size:14px}
}
/* meta over photography needs the full-strength color to hold */
.hero__type .t-meta{color:var(--paper)}
.tag__sub{text-wrap:balance}

/* the label is a sibling of the photo, not inside it, so on phones it can
   sit on the photo's bottom edge instead of covering the piece. on desktop
   it pins to the photo's lower-left corner: the photo column starts at
   1/(1+1.45) of the band. */
@media (min-width:900px){
  .band--flip > .tag{left:calc(100% / 2.45 + clamp(16px,2.2vw,32px))}
}
@media (max-width:899px){
  .tag{position:relative; left:auto; bottom:auto; margin:-44px 0 0 16px}
}

/* the footer's ground runs edge to edge (the pinned hero showed past its
   1760px cap on wide screens); only its contents keep the measure */
footer{
  max-width:none;
  padding-left:max(calc(var(--gutter) + var(--frame)), calc((100% - 1760px) / 2 + var(--gutter) + var(--frame)));
  padding-right:max(calc(var(--gutter) + var(--frame)), calc((100% - 1760px) / 2 + var(--gutter) + var(--frame)));
}

/* ---------- review only: version switcher in the top bar. remove before launch ---------- */
.top__right{display:flex; align-items:baseline; gap:clamp(20px,2.4vw,36px)}
.vswitch{display:flex; gap:12px; pointer-events:auto}
.vswitch a{
  font-size:13px; letter-spacing:.02em; color:var(--paper-dim); text-decoration:none;
  border-bottom:1px solid transparent; padding-bottom:2px;
}
.vswitch a:hover{color:var(--paper)}
.vswitch a[aria-current]{color:var(--paper); border-bottom-color:currentColor}

/* ---------- review only: six-way switcher, originals beside foundation versions ---------- */
.vswitch{gap:20px}
.vs-pair{display:flex; gap:8px}
.vswitch a{position:relative}
.vswitch a::after{content:""; position:absolute; inset:-14px -6px}
@media (max-width:899px){
  .vswitch{
    position:fixed; left:50%; transform:translateX(-50%);
    bottom:calc(16px + env(safe-area-inset-bottom));
    padding:10px 24px; border-radius:999px; pointer-events:auto;
    background:rgba(18,18,20,.72); -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px);
  }
  .vswitch a{color:rgba(233,229,223,.7)}
  .vswitch a[aria-current]{color:#e9e5df}
}

/* ============================================================
   FOUNDATION SPACING AND PROPORTION, 2026-10-02 (FOUNDATION.md)
   8px steps only: 8 16 24 32 48 64 96 128 192. one rail: the name,
   every copy block, the hero type and the footer start at the same x
   (the sheet's frame plus --pad). images in the pattern sections are
   3:2 and identical in size; copy sits middle-aligned beside them.
   ============================================================ */
:root{--pad:24px; --sec:96px}
@media (min-width:900px){ :root{--pad:64px; --sec:128px} }
@media (min-width:1440px){ :root{--pad:96px} }

/* the rail */
.top{padding:24px calc(var(--frame) + var(--pad)) 0}
@media (min-width:900px){
  .top{padding:32px calc(var(--frame) + var(--pad)) 0}
  .hero__type{left:calc(var(--frame) + var(--pad)); bottom:96px}
}
@media (max-width:899px){
  .hero__type{left:calc(var(--frame) + var(--pad)); right:calc(var(--frame) + var(--pad)); bottom:64px}
}
.hero__type{gap:16px}

/* sections: one gap between them, 128 (96 on phones) */
.band{min-height:0; margin-top:var(--sec); align-items:center}
@media (max-width:899px){ .band{margin-top:var(--sec)} }

/* 3:2 frames, the same size in every pattern section */
.band__media{min-height:0; aspect-ratio:3 / 2}
@media (max-width:899px){ .band__media{min-height:0} }

/* copy beside its image: eyebrow 8, then 16 between heading and body */
.band__copy{gap:0; padding:64px var(--pad)}
.band__copy > *{margin:0}
.band__copy > * + *{margin-top:16px}
.band__copy > .label + *{margin-top:8px}
@media (max-width:899px){ .band__copy{padding:24px var(--pad) 0} }

/* the wall label: 32 in from the photo's corner; on phones it overlaps the
   photo's bottom edge by 48 */
.tag{left:32px; bottom:32px}
@media (min-width:900px){ .band--flip > .tag{left:calc(100% / 2.45 + 32px)} }
@media (max-width:899px){ .tag{margin:-48px 0 0 var(--pad)} }

/* the inquiry */
section.opt{padding:192px calc(var(--frame) + var(--pad))}
@media (max-width:899px){ section.opt{padding:96px calc(var(--frame) + var(--pad)) 128px} }
.opt__inner{max-width:none; gap:64px}
form{gap:32px}
.field{gap:8px}
.choices{margin-top:16px}
.tailfields{gap:24px}
.branch{margin-bottom:24px}
.branch .wall + .field, .branch p + .field{margin-top:24px}
.trail{margin:32px 0 24px}
.opt .t-h2{margin-bottom:24px}

/* footer on the rail */
footer{padding:32px calc(var(--frame) + var(--pad)) 48px}

/* ---------- on process: the one break, a pinned scroll story ----------
   Von Restorff: the only section that behaves differently, so it is the
   one remembered. the stage pins for 220svh of scroll (legible motion),
   the copy holds beneath the frame the whole time (proximity), and the
   page returns to the pattern straight after. */
.story{display:block; height:320svh; background:none}
.story__stage{
  position:sticky; top:0; height:100svh; box-sizing:border-box;
  display:grid; grid-template-rows:minmax(0,1fr) auto; row-gap:32px;
  padding:96px var(--pad) 48px;
}
.story__frame{position:relative; overflow:hidden; min-height:0; background:#1b1b1e}
.story__img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  will-change:transform, opacity; transform-origin:50% 45%;
}
.story__img--palette{opacity:0}
.story__copy{max-width:62ch}
.story__copy > *{margin:0}
.story__copy > .label + *{margin-top:8px}
@media (max-width:899px){
  .story__stage{padding:72px var(--pad) 32px; row-gap:24px}
}
@media (prefers-reduced-motion:reduce){
  .story{height:auto}
  .story__stage{position:static; height:auto}
  .story__frame{aspect-ratio:3 / 2}
  .story__img--raw{display:none}
  .story__img--palette{opacity:1}
}
.story__copy .wall{max-width:58ch}

/* ---------- 2026-10-02, later (Michael) ---------- */

/* the name: capitals, thin. capitals need tracking to read evenly */
.top .t-name{text-transform:uppercase; font-weight:200; letter-spacing:.14em}

/* In Place: the photo and its caption are one figure. the caption follows
   museum convention (Chicago Manual of Style; College Art Association
   captions): title in italics with its subtitle, date, then medium and
   height x width; availability last. set tight under the image, 16 below. */
.band__fig{margin:0; min-width:0}
@media (min-width:900px){ .band--flip > .band__fig{order:2} }
.caption{
  margin:16px 0 0; font-size:14px; line-height:24px; font-weight:300;
  color:var(--paper-dim); letter-spacing:.01em;
}
.caption__title{color:var(--paper)}
.caption__title i{font-style:italic}
.caption__line{white-space:normal}
@media (min-width:900px){ .caption__line{display:block} }
@media (max-width:899px){
  .caption{padding:0 var(--pad)}
  .caption__line{display:block}
}

/* the story: a 3:2 frame, shown whole, centered in the pinned stage, with
   the copy tight beneath it */
.story__stage{display:flex; align-items:center; justify-content:center; grid-template-rows:none}
.story__inner{width:min(100%, calc((100svh - 316px) * 1.5))}
.story__frame{aspect-ratio:3 / 2; width:100%}
.story__copy{margin-top:32px}
/* zoom origin: the urchin on its lilac chip */
.story__img--palette{transform-origin:43% 37%}
@media (max-width:899px){
  .story__inner{width:100%}
  .story__copy{margin-top:24px}
}
/* the palette is shown at full resolution (2400): the close-in magnifies it 2.6x */
/* phones: the caption groups with its photo (16), the copy starts a group (48) */
@media (max-width:899px){ .band__fig + .band__copy{padding-top:48px} }

/* ---------- phones, 2026-10-02 (Michael): the hero zoomed in too far ----------
   a wide photo filling a tall screen is already a close crop; the extra 12%
   overscan and the parallax made it closer. on phones: almost no overscan, no
   parallax, and the crop moves left to the sharp middle where the rows recede,
   so more and smaller beads show. */
@media (max-width:899px){
  .hero .plate{inset:-2% 0; background-position:42% 50%; transform:none !important}
}

/* ---------- contrast over photographs, 2026-10-02 ----------
   measured, not assumed: text was hidden, the photo behind it sampled, and the
   light end (95th percentile) of those pixels compared with the text color.
   heroes were failing (as low as 1.7:1). a gradient behind the copy only: dark
   at the foot where the copy sits, gone by three quarters up, so the top of the
   photograph stays as shot. */
/* dialed back to halfway between none and the full scrim (Michael, 2026-10-03) */
.hero::before{
  content:""; position:absolute; inset:0; z-index:2; pointer-events:none;
  background:linear-gradient(to top, rgba(10,10,11,.43) 0%, rgba(10,10,11,.37) 38%,
    rgba(10,10,11,.23) 56%, rgba(10,10,11,0) 76%);
}
.top::before{
  background:linear-gradient(to bottom, rgba(18,18,20,.79) 0%, rgba(18,18,20,.54) 43%,
    rgba(18,18,20,.19) 78%, rgba(18,18,20,0) 100%);
}

/* ---------- phone grid, 2026-10-03 (Michael) ----------
   two image widths only: full bleed, and the inset width (the 13px frame).
   copy sits 24px from the screen edge, v4's phone margin: frame 13 + pad 11. */
@media (max-width:899px){
  :root{--pad:11px}
  /* on process: the frame fills the inset width like every other image */
  .story__stage{padding-left:0; padding-right:0}
  .story__copy{padding-inline:var(--pad)}
}

/* ---------- v2 story: three images (2026-10-03). longer pin for the third ---------- */
.story{height:420svh}
.story__img--made{opacity:0}
@media (prefers-reduced-motion:reduce){ .story__img--palette{opacity:0} .story__img--made{opacity:1} }

/* ---------- v2b: the thread (2026-10-03) ----------
   at rest the letters sit at 5.2:1 on the ground (above WCAG's 4.5); in the
   window they go to full white, 18:1. color only, so nothing reflows. */
.sr-only{position:absolute; width:1px; height:1px; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
.weave-text .ch{color:rgba(233,229,223,.55)}
@media (prefers-reduced-motion:reduce){ .weave-text .ch{color:var(--paper-dim) !important} }

/* ---------- phones, 2026-10-03 (Michael): steady images ----------
   the pinned hero stays pinned, but sized to the tallest screen height (lvh) so it
   cannot re-scale when iOS collapses its toolbars: that re-scale was the zoom jump.
   no parallax on phones, so no overscan: images show their whole frame. */
@media (max-width:899px){
  .hero .plate{inset:auto; top:0; left:0; right:0; height:100lvh; transform:none !important}
  .band__media .plate{inset:0}
}

/* the top fade ends as far below the name as the name sits below the top of the screen
   (Michael, 2026-10-03): 24px on phones, 32px on desktop, the bar's own top padding */
.top::before{height:calc(100% + 24px);
  background:linear-gradient(to bottom, rgba(18,18,20,.86) 0%, rgba(18,18,20,.74) 55%,
    rgba(18,18,20,.3) 80%, rgba(18,18,20,0) 100%)}
@media (min-width:900px){ .top::before{height:calc(100% + 29px)} }

/* ---------- the top fade, clean (Michael, 2026-10-03) ----------
   one ease-in-out curve from the top of the screen to its end, no hold and no extra
   stops: the old version held full strength through the name, then dropped steeply,
   which read as a line under the name. it ends as far below the name as the name sits
   below the top of the screen (the bar's own top padding: 24 phones, 32 desktop). */
.top::before{height:calc(100% + 24px); -webkit-mask-image:none; mask-image:none;
  background:linear-gradient(to bottom, rgba(18,18,20,0.860) 0.0%, rgba(18,18,20,0.845) 8.3%, rgba(18,18,20,0.802) 16.7%, rgba(18,18,20,0.734) 25.0%, rgba(18,18,20,0.645) 33.3%, rgba(18,18,20,0.541) 41.7%, rgba(18,18,20,0.430) 50.0%, rgba(18,18,20,0.319) 58.3%, rgba(18,18,20,0.215) 66.7%, rgba(18,18,20,0.126) 75.0%, rgba(18,18,20,0.058) 83.3%, rgba(18,18,20,0.015) 91.7%, rgba(18,18,20,0.000) 100.0%)}
@media (min-width:900px){ .top::before{height:calc(100% + 29px)} }
