/* ============================================================================
   VEIL & THORN — COMPONENTS
   Ticker, flash wall, work grid, cards, events, FAQ, booking form.
   ========================================================================= */

/* ----------------------------------------------------------------------------
   Ticker
   ------------------------------------------------------------------------- */
.ticker{
  border-top:var(--rule); border-bottom:var(--rule);
  background:var(--pink); color:var(--ink); overflow:hidden; padding:10px 0;
}
.ticker__track{display:flex; width:max-content; animation:roll 46s linear infinite}
.ticker span{
  font-family:var(--display); font-size:clamp(16px,1.8vw,24px);
  text-transform:uppercase; letter-spacing:.05em; padding:0 22px; white-space:nowrap;
}
.ticker span i{font-style:normal; opacity:.5}
@keyframes roll{to{transform:translateX(-50%)}}

/* ----------------------------------------------------------------------------
   The flash wall — a camera pushed down the z axis as you scroll
   ------------------------------------------------------------------------- */
.tunnel{height:520vh; position:relative}
.tunnel__stage{
  position:sticky; top:0; height:100svh; overflow:hidden;
  perspective:900px; perspective-origin:50% 50%;
  background:radial-gradient(80% 60% at 50% 50%, #1D1420 0%, #0B0A0C 70%);
}
.tunnel__cam{position:absolute; inset:0; transform-style:preserve-3d; will-change:transform}

.flash{
  position:absolute; left:50%; top:50%; width:260px;
  transform-style:preserve-3d; will-change:transform, opacity;
  background:var(--pink); padding:12px 12px 34px;
  box-shadow:0 22px 60px rgba(0,0,0,.65);
  /* The sheen below is multiplied, and multiply blends with whatever is behind
     the element. In the tunnel each sheet carries an opacity that isolates it
     by accident; with motion reduced that opacity is forced to 1 and the blend
     leaks onto the page, staining the sheets unevenly. Isolate it on purpose. */
  isolation:isolate;
}
.flash::before{
  content:""; position:absolute; inset:0; pointer-events:none; mix-blend-mode:multiply;
  background:
    radial-gradient(120% 80% at 30% 10%, rgba(255,255,255,.4), transparent 60%),
    radial-gradient(90% 70% at 80% 100%, rgba(150,70,110,.24), transparent 60%);
}
.flash svg{width:100%; height:auto}
.flash svg [data-ink]{fill:none; stroke:var(--ink-line); stroke-width:3; stroke-linecap:round; stroke-linejoin:round}
.flash svg [data-fill]{fill:var(--ink-line); stroke:none}
.flash svg [data-red]{fill:none; stroke:var(--ink-line); stroke-width:3; stroke-linecap:round; opacity:.55}

/* A scanned sheet. The PNG has its paper knocked out to transparency, so what
   you see is ink sitting on the pink card itself rather than a white rectangle
   pasted onto one.

   The designs range from tall pendants to wide chest pieces. Giving every card
   the same shape and fitting the drawing inside it keeps the wall reading as a
   wall, instead of a jumble of different-sized rectangles. The card's own
   padding does the framing, so the tag never sits on top of the artwork. */
.flash--photo{
  aspect-ratio:3/4;
  display:flex; align-items:center; justify-content:center;
}
.flash--photo img{width:100%; height:100%; object-fit:contain}
.flash.gone img{opacity:.4}

.flash__tag{
  position:absolute; left:12px; right:12px; bottom:10px;
  display:flex; justify-content:space-between; align-items:baseline; gap:8px;
  font-family:var(--data); font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:#8A4E6B;
}
.flash__tag b{color:var(--ink); font-weight:700}
.flash.gone .flash__tag b{color:#9A6A80; text-decoration:line-through}

.tunnel__title{
  position:absolute; left:var(--pad); top:clamp(84px,12vh,130px); z-index:5;
  pointer-events:none; max-width:min(460px,58vw); isolation:isolate;
}
/* Sheets fly in front of this heading, which is the point — but the copy still
   has to be readable while they do. A soft scrim keeps it legible without
   breaking the illusion that you're moving through the wall. */
.tunnel__title::before{
  content:""; position:absolute; inset:-30px -60px -30px -40px; z-index:-1;
  background:radial-gradient(65% 70% at 22% 45%, rgba(11,10,12,.88) 0%, rgba(11,10,12,.6) 45%, transparent 78%);
}
.tunnel__title .h-lg{margin:0 0 14px}
.tunnel__title p{color:var(--bone-soft); font-size:15px; max-width:34ch; margin:0}

.tunnel__hud{
  position:absolute; inset:auto var(--pad) clamp(22px,4vh,44px) var(--pad); z-index:5;
  display:flex; justify-content:space-between; align-items:flex-end; gap:20px;
  pointer-events:none;
}
.tunnel__hud .eyebrow{margin:0 0 6px}
.tunnel__hud-right{text-align:right}
.hud__meter{width:min(280px,40vw); height:2px; background:rgba(253,194,219,.18); position:relative; margin-top:8px}
.hud__meter i{position:absolute; left:0; top:0; bottom:0; background:var(--pink); width:0}

.tunnel__fog{
  position:absolute; inset:0; z-index:4; pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(11,10,12,.92) 0%, transparent 22%, transparent 72%, rgba(11,10,12,.96) 100%);
}

@media(max-width:700px){
  .tunnel__title{max-width:none; right:var(--pad)}
  .tunnel__title p{display:none}
}

/* Reduced motion: the tunnel becomes an ordinary grid of flash sheets */
@media (prefers-reduced-motion: reduce){
  .tunnel{height:auto}
  .tunnel__stage{position:static; height:auto; padding:80px var(--pad); perspective:none; overflow:visible}
  .tunnel__cam{
    position:static; transform:none !important; display:grid;
    grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); gap:20px; margin-top:32px;
  }
  .flash{position:static !important; width:auto !important; transform:none !important; opacity:1 !important}
  .tunnel__hud,.tunnel__fog,.tunnel__title{position:static; margin-bottom:18px}
  .tunnel__fog{display:none}
  /* That scrim is absolutely positioned against .tunnel, not against the
     heading. Once the heading goes static it stops sitting over the sheets and
     starts sitting over the whole section, staining every sheet on the left
     half of the grid. Nothing flies in front of the copy here anyway. */
  .tunnel__title::before{display:none}
}

/* ----------------------------------------------------------------------------
   Selected work
   ------------------------------------------------------------------------- */
.work{display:grid; grid-template-columns:repeat(12,1fr); gap:clamp(16px,2.2vw,32px)}
.piece{position:relative; grid-column:span 4; margin:0}
.piece--wide{grid-column:span 6}
.piece--tall{grid-column:span 4}
.piece--push{margin-top:clamp(20px,6vw,100px)}

.plate{
  position:relative; overflow:hidden; aspect-ratio:4/5;
  display:grid; place-items:center; padding:8%;
  transition:transform .5s cubic-bezier(.2,.8,.2,1);
}
.plate--skin{background:linear-gradient(160deg,#D9B79A,#B98F6E)}
.plate--paper{background:linear-gradient(160deg,var(--pink),#E39BBE)}
.plate::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  mix-blend-mode:multiply; opacity:.45;
  background:radial-gradient(70% 60% at 30% 20%, transparent 40%, rgba(60,20,40,.5) 100%);
}
/* Over a drawing that vignette is atmosphere. Over a real photograph — already
   shot under studio light, on a near-black page — it just turns the edges to
   mud, so it comes most of the way back off. */
.plate--photo::after{opacity:.16}
/* Photographs of black linework on skin sit very close to the page in tone.
   A touch of contrast lifts them off it. Deliberately small: the promise on
   the page is that nothing is filtered, and this must not become one. */
.plate--photo img{filter:contrast(1.06) saturate(.96)}
.plate img{width:100%; height:100%; object-fit:cover; position:absolute; inset:0}
.plate svg{width:100%; height:auto; position:relative; z-index:2}

/* Linework draws itself on in pink, then cures to black — stencil to ink. */
.plate svg [data-ink]{
  fill:none; stroke:var(--pink); stroke-width:3.2;
  stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:1; stroke-dashoffset:1;
  transition:stroke-dashoffset 1.9s cubic-bezier(.4,0,.2,1),
             stroke 1.1s ease 1.35s, stroke-width .9s ease 1.35s;
}
.plate svg [data-fill]{
  fill:var(--pink); stroke:none; opacity:0;
  transition:opacity .8s ease 1.5s, fill 1.1s ease 1.5s;
}
.plate svg [data-red]{
  fill:none; stroke:var(--pink); stroke-width:3.2; stroke-linecap:round;
  stroke-dasharray:1; stroke-dashoffset:1;
  transition:stroke-dashoffset 1.9s cubic-bezier(.4,0,.2,1) .25s, stroke 1.1s ease 1.6s;
}
.piece.inked .plate svg [data-ink]{stroke-dashoffset:0; stroke:var(--ink-line); stroke-width:3.6}
.piece.inked .plate svg [data-fill]{opacity:1; fill:var(--ink-line)}
.piece.inked .plate svg [data-red]{stroke-dashoffset:0; stroke:var(--ink-line); opacity:.6}

.piece__meta{
  display:flex; justify-content:space-between; gap:14px;
  padding-top:12px; border-top:var(--rule); margin-top:14px;
}
.piece__meta h3{
  margin:0; font-family:var(--display); font-weight:400;
  font-size:clamp(15px,1.5vw,20px); text-transform:uppercase; letter-spacing:.03em;
}
.piece__meta .small{text-align:right; white-space:nowrap}

.work__more{margin:clamp(30px,4.5vw,60px) 0 0; text-align:center}

.badge{
  position:absolute; z-index:3; left:0; top:0;
  font-family:var(--data); font-size:10px; letter-spacing:.18em;
  text-transform:uppercase; padding:6px 11px; background:var(--ink); color:var(--bone);
}
.badge--flash{background:var(--pink); color:var(--ink)}

@media(max-width:900px){
  .piece,.piece--wide,.piece--tall{grid-column:span 6}
  .piece--push{margin-top:0}
}
@media(max-width:560px){ .piece,.piece--wide,.piece--tall{grid-column:span 12} }

@media (prefers-reduced-motion: reduce){
  .plate svg [data-ink],.plate svg [data-red]{stroke-dashoffset:0; stroke:var(--ink-line)}
  .plate svg [data-fill]{opacity:1; fill:var(--ink-line)}
}

/* ----------------------------------------------------------------------------
   Cards, tables, panels
   ------------------------------------------------------------------------- */
.card{border:var(--rule); background:var(--ink-2)}
.card__hd{
  padding:14px 20px; border-bottom:var(--rule);
  display:flex; justify-content:space-between; align-items:center; gap:12px;
}
.card__hd--split{border-top:var(--rule)}
.card__hd .eyebrow{margin:0}
.card__note{margin:0; padding:12px 20px 14px; border-top:1px solid rgba(253,194,219,.08)}

.table{width:100%; border-collapse:collapse; font-family:var(--data); font-size:13.5px}
.table td{padding:11px 20px; border-bottom:1px solid rgba(253,194,219,.08)}
.table td:first-child{
  color:var(--mute); letter-spacing:.08em; text-transform:uppercase; font-size:11.5px;
}
.table td:last-child{text-align:right; color:var(--bone)}
.table tr:last-child td{border-bottom:0}
.table tr.today td{background:rgba(253,194,219,.11)}
.table tr.today td:first-child{color:var(--pink)}
.table tr.closed td:last-child{color:var(--mute)}

.panel{border:var(--rule); background:var(--ink-2); padding:clamp(20px,2.6vw,30px)}
.panel .h-md{margin:0 0 12px; color:var(--pink)}
.panel p{margin:0; color:var(--bone-soft); font-size:15px}

.addr{margin:0 0 18px; font-family:var(--data); font-size:14px; line-height:1.9; color:var(--bone)}
.addr a{border-bottom:1px solid rgba(253,194,219,.4)}
.addr a:hover{color:var(--pink)}

.social{list-style:none; margin:0; padding:0; display:grid; gap:8px}
.social a{
  display:flex; justify-content:space-between; gap:14px; align-items:baseline;
  padding:11px 14px; border:var(--rule-faint); background:rgba(253,194,219,.03);
  font-family:var(--data); font-size:12.5px; transition:border-color .25s, background .25s;
}
.social a:hover{border-color:var(--pink); background:rgba(253,194,219,.08)}
.social a b{font-weight:400; letter-spacing:.16em; text-transform:uppercase; color:var(--pink)}
.social a span{color:var(--mute)}

/* ----------------------------------------------------------------------------
   The studio photograph
   ------------------------------------------------------------------------- */
.studio__shot{margin:0; border:var(--rule); background:var(--ink-2); padding:10px}
/* A fixed 4/5 box with the crop pulled upwards, so the frame stays tidy
   whatever shape the next photo dropped in here happens to be.
   `height:auto` is load-bearing: the img carries a height attribute (which
   stops the page jumping as it loads) and that lands as a presentational hint
   of height:1400px. A definite height makes the browser ignore aspect-ratio
   altogether, and the photo comes out a metre tall. */
.studio__shot img{
  width:100%; height:auto; aspect-ratio:4/5;
  object-fit:cover; object-position:50% 32%;
  filter:saturate(.9) contrast(1.03);
}
.studio__shot figcaption{
  padding:11px 4px 3px; text-align:center; letter-spacing:.12em; text-transform:uppercase;
}

/* ----------------------------------------------------------------------------
   The map
   ------------------------------------------------------------------------- */
.studio__map{margin:0; border:var(--rule); background:var(--ink-2); padding:10px}
/* Direct child only. Without the >, this also catches the OpenStreetMap credit
   inside the caption, turning that link into a full-width block with a rule
   stretched across the panel. */
.studio__map > a{position:relative; display:block; overflow:hidden}
.studio__map img{width:100%; height:auto; display:block; transition:transform .6s cubic-bezier(.2,.8,.2,1)}
.studio__map > a:hover img{transform:scale(1.03)}

/* Sits over the map rather than under it, so the panel doesn't grow a whole
   extra row of furniture just to say "tap me". */
.studio__map-cta{
  position:absolute; right:10px; bottom:10px;
  padding:8px 14px; background:var(--ink); color:var(--bone);
  font-family:var(--data); font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  transition:background .25s, color .25s;
}
.studio__map > a:hover .studio__map-cta{background:var(--pink); color:var(--ink)}
.studio__map figcaption{padding:12px 4px 3px; text-align:center; line-height:1.7}
.studio__map figcaption a{color:var(--mute); border-bottom:1px solid rgba(253,194,219,.25)}
.studio__map figcaption a:hover{color:var(--pink)}

/* ----------------------------------------------------------------------------
   What clients say — a rail that slides across on its own
   ------------------------------------------------------------------------- */

/* Bleeds out past the section padding to both screen edges, and the mask fades
   the quotes out as they reach them instead of chopping them off mid-word. */
.says{
  position:relative; overflow:hidden;
  margin:0 calc(var(--pad) * -1); padding:4px 0;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image:linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.says__track{
  display:flex; width:max-content;
  animation:saysRoll 40s linear infinite;
  will-change:transform;
}
@keyframes saysRoll{ to{ transform:translateX(-50%) } }

/* Stop for anyone reading, tabbing through, or who has pressed the button. */
.says:hover .says__track,
.says:focus-within .says__track,
.says.is-paused .says__track{ animation-play-state:paused }

.say{
  position:relative; flex:0 0 clamp(250px, 27vw, 340px);
  margin-right:clamp(14px,2vw,22px);
  border:var(--rule); background:var(--ink-2);
  padding:clamp(26px,2.8vw,34px) clamp(20px,2.4vw,28px) clamp(18px,2vw,24px);
  display:flex; flex-direction:column; gap:14px;
}
.say__mark{
  position:absolute; top:-2px; left:14px;
  font-family:var(--display); font-size:64px; line-height:1;
  color:var(--pink); opacity:.28; pointer-events:none;
}
.say blockquote{
  margin:0; flex:1; font-size:15.5px; line-height:1.7; color:var(--bone);
}
.say figcaption{
  margin:0; padding-top:12px; border-top:var(--rule-faint);
  letter-spacing:.14em; text-transform:uppercase;
}

.says__foot{display:flex; justify-content:flex-end; margin-top:18px}
.says__toggle{
  cursor:pointer; background:transparent; border:1px solid rgba(253,194,219,.28);
  padding:8px 18px; color:var(--bone-soft);
  font-family:var(--data); font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  transition:color .25s, border-color .25s, background .25s;
}
.says__toggle:hover{color:var(--pink); border-color:var(--pink); background:rgba(253,194,219,.06)}

/* Reduced motion: nothing slides. The rail becomes an ordinary row you push
   along yourself, and the duplicate set — which only exists to hide the loop's
   seam — would just read as the same four quotes twice, so it goes. */
@media (prefers-reduced-motion: reduce){
  .says{overflow-x:auto; margin:0; padding-bottom:10px; -webkit-mask-image:none; mask-image:none}
  .says__track{animation:none; transform:none; width:auto}
  .say--dup{display:none}
  .says__foot{display:none}
}

/* ----------------------------------------------------------------------------
   Events / on the road
   ------------------------------------------------------------------------- */
.events{display:grid; gap:12px}
.events__list{display:grid; gap:12px; border-top:var(--rule)}
.event{
  display:grid; grid-template-columns:1.4fr 1fr 1fr auto;
  gap:12px 24px; align-items:baseline;
  padding:clamp(18px,2.4vw,26px) 0; border-bottom:var(--rule);
}
.event h3{
  margin:0; font-family:var(--display); font-weight:400;
  font-size:clamp(19px,2.2vw,28px); text-transform:uppercase; letter-spacing:.02em;
}
.event__place,.event__date{font-family:var(--data); font-size:13px; color:var(--bone-soft); margin:0}
.event__place::before{content:"◦ "; color:var(--pink)}
.event__status{
  justify-self:end; font-family:var(--data); font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase; padding:5px 11px;
  border:1px solid currentColor; white-space:nowrap;
}
.event__status.is-confirmed{color:var(--pink)}
.event__status.is-pending{color:var(--mute)}
.event__status.is-guest{color:var(--pink-hot)}

/* Featured show — the convention's own flyer, pinned to the page.
   The artwork is left in its own colours rather than pulled toward the pink;
   the tilt, shadow and bone edge are what say "this is a flyer", so the clash
   reads as deliberate instead of as a broken swatch. */
.event-feature{
  display:grid; grid-template-columns:minmax(0,auto) minmax(0,1fr);
  gap:clamp(22px,4vw,52px); align-items:center;
  padding:clamp(24px,3.4vw,42px) 0; border-bottom:var(--rule);
}
.event-feature__flyer{ width:clamp(220px,26vw,360px); }
.event-feature__flyer img{
  display:block; width:100%; height:auto;
  transform:rotate(-1.6deg);
  /* The flyer is cut out to its torn edge, so the lift has to be a drop-shadow
     filter rather than box-shadow — box-shadow would draw the rectangle the
     artwork no longer has. */
  filter:drop-shadow(0 16px 26px rgba(0,0,0,.85)) drop-shadow(0 1px 0 rgba(253,194,219,.14));
  transition:transform .5s cubic-bezier(.2,.7,.3,1), filter .5s;
}
.event-feature:hover .event-feature__flyer img{
  transform:rotate(0deg) translateY(-4px);
  filter:drop-shadow(0 24px 34px rgba(0,0,0,.9)) drop-shadow(0 1px 0 rgba(253,194,219,.22));
}
.event-feature__body{display:grid; gap:10px; justify-items:start}
.event-feature__body .event__status{justify-self:start}
.event-feature__body h3{
  margin:0; font-family:var(--display); font-weight:400;
  font-size:clamp(26px,3.6vw,42px); text-transform:uppercase;
  letter-spacing:.02em; line-height:1.05;
}
.event-feature__cta{
  margin-top:6px; font-family:var(--data); font-size:12px;
  letter-spacing:.14em; text-transform:uppercase; color:var(--pink);
  border-bottom:1px solid rgba(253,194,219,.4); padding-bottom:3px;
}
.event-feature__cta:hover{color:var(--pink-hot); border-bottom-color:var(--pink-hot)}
@media(max-width:860px){
  .event-feature{grid-template-columns:1fr; gap:20px; justify-items:start}
  .event-feature__flyer{width:min(78vw,340px)}
}
@media(prefers-reduced-motion:reduce){
  .event-feature__flyer img,
  .event-feature:hover .event-feature__flyer img{transform:none; transition:none}
}
.events__empty{padding:28px 0; color:var(--bone-soft)}
.events__note{margin:26px 0 0}
.events__note a{color:var(--pink); border-bottom:1px solid rgba(253,194,219,.4)}
@media(max-width:760px){
  .event{grid-template-columns:1fr auto; gap:6px 16px}
  .event h3{grid-column:1}
  .event .event__status{grid-row:1; grid-column:2}
  .event .event__place,.event .event__date{grid-column:1/-1}
}

/* ----------------------------------------------------------------------------
   FAQ
   ------------------------------------------------------------------------- */
.faq{border-top:var(--rule); max-width:78ch}
.faq__item{border-bottom:var(--rule)}
.faq__item summary{
  cursor:pointer; list-style:none; padding:clamp(16px,2vw,22px) 40px clamp(16px,2vw,22px) 0;
  position:relative; font-family:var(--display); font-weight:400;
  font-size:clamp(18px,2vw,25px); text-transform:uppercase; letter-spacing:.02em;
  transition:color .25s;
}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary:hover{color:var(--pink)}
.faq__item summary::after{
  content:""; position:absolute; right:6px; top:50%; width:11px; height:11px;
  border-right:1.5px solid var(--pink); border-bottom:1.5px solid var(--pink);
  transform:translateY(-70%) rotate(45deg); transition:transform .3s;
}
.faq__item[open] summary::after{transform:translateY(-20%) rotate(-135deg)}
.faq__item[open] summary{color:var(--pink)}
.faq__body{padding:0 40px 22px 0}
.faq__body p{margin:0; color:var(--bone-soft); font-size:15.5px; max-width:64ch}
.faq__body a{color:var(--pink); border-bottom:1px solid rgba(253,194,219,.4)}

/* ----------------------------------------------------------------------------
   Long-form pages (privacy)
   ----------------------------------------------------------------------------
   Narrow measure and generous leading. Legal copy only gets read if it's
   comfortable to read, and a page nobody reads is no protection at all.
   ------------------------------------------------------------------------- */
.sec--legal{padding-top:clamp(120px,17vh,190px)}
.prose{max-width:68ch}
.prose h2{
  margin:clamp(34px,4vw,52px) 0 12px;
  font-family:var(--display); font-weight:400;
  font-size:clamp(20px,2.3vw,29px); text-transform:uppercase; letter-spacing:.02em;
  color:var(--pink);
}
.prose h2:first-child{margin-top:0}
.prose p{margin:0 0 14px; color:var(--bone-soft); font-size:15.5px; line-height:1.75}
.prose ul{margin:0 0 16px; padding-left:20px; color:var(--bone-soft); font-size:15.5px; line-height:1.75}
.prose li{margin-bottom:5px}
.prose li::marker{color:var(--pink)}
.prose b{color:var(--bone); font-weight:600}
.prose a{color:var(--pink); border-bottom:1px solid rgba(253,194,219,.4)}
.prose a:hover{border-bottom-color:var(--pink)}
.prose .small{margin-bottom:14px}

/* Blanks only the studio owner can fill in. Deliberately loud: a privacy
   notice that goes live still saying "to be added" is worse than one that
   never mentioned the point, so this has to be impossible to skim past. */
.todo{
  display:inline-block; background:var(--pink-hot); color:var(--ink);
  padding:1px 8px; border-radius:2px; font-weight:700;
  font-family:var(--data); font-size:12.5px; letter-spacing:.04em;
}

/* ----------------------------------------------------------------------------
   Booking form
   ------------------------------------------------------------------------- */
.book{
  border:1px solid rgba(253,194,219,.22); background:var(--ink-2);
  padding:clamp(24px,4vw,52px); position:relative; overflow:hidden;
}
.book::before{
  content:"ENQUIRY"; position:absolute; right:-30px; top:26px;
  transform:rotate(90deg); transform-origin:100% 0;
  font-family:var(--data); font-size:10.5px; letter-spacing:.4em;
  color:rgba(253,194,219,.2);
}

.grid2{display:grid; grid-template-columns:1fr 1fr; gap:18px 22px}
.field{display:flex; flex-direction:column; gap:7px}
.field.full{grid-column:1/-1}
.field label{
  font-family:var(--data); font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--mute);
}
.field input,.field select,.field textarea{
  background:transparent; border:0; border-bottom:1px solid rgba(253,194,219,.26);
  color:var(--bone); font-family:var(--body); font-size:15.5px; padding:9px 0;
  transition:border-color .3s;
}
.field textarea{resize:vertical; min-height:92px}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none; border-bottom-color:var(--pink);
}
.field select{appearance:none; cursor:pointer}
.field select option{background:var(--ink-2); color:var(--bone)}
.field input::placeholder,.field textarea::placeholder{color:#6C636C}
.field.invalid input,.field.invalid select{border-bottom-color:var(--pink-hot)}
.field__opt{
  font-family:var(--data); font-size:9.5px; letter-spacing:.16em;
  color:var(--pink-deep); margin-left:8px;
}
.field__hint{margin:8px 0 0; max-width:58ch}

/* ----------------------------------------------------------------------------
   Reference images
   ----------------------------------------------------------------------------
   The real <input type="file"> is kept rather than hidden behind a fake button:
   it is already keyboard reachable, already announces itself properly, and
   already handles the phone's "take a photo" option. Only the button inside it
   is restyled, which ::file-selector-button does natively.
   ------------------------------------------------------------------------- */
.field input[type="file"]{
  border-bottom:0; padding:4px 0 0;
  font-family:var(--data); font-size:12px; color:var(--mute); cursor:pointer;
}
.field input[type="file"]::file-selector-button{
  margin-right:14px; cursor:pointer;
  background:transparent; border:1px solid rgba(253,194,219,.45); color:var(--bone);
  font-family:var(--data); font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  padding:10px 18px;
  transition:background .25s, color .25s, border-color .25s;
}
.field input[type="file"]::file-selector-button:hover{
  background:var(--pink); border-color:var(--pink); color:var(--ink);
}
.field.invalid input[type="file"]::file-selector-button{border-color:var(--pink-hot)}

.filelist{
  list-style:none; margin:14px 0 0; padding:0;
  display:grid; gap:1px; font-family:var(--data); font-size:12px;
}
.filelist li{
  display:flex; justify-content:space-between; align-items:baseline; gap:14px;
  padding:8px 12px; background:rgba(253,194,219,.04); color:var(--bone-soft);
}
.filelist li span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.filelist li b{font-weight:400; color:var(--mute); white-space:nowrap}
.filelist__over{background:rgba(249,143,192,.12)}
.filelist__over b{color:var(--pink-hot)}
.filelist__total{background:transparent; border-top:var(--rule-faint); color:var(--mute)}
.field__err{
  font-family:var(--data); font-size:11px; letter-spacing:.06em;
  color:var(--pink-hot); margin:0;
}

/* Honeypot — off-screen, never focusable, invisible to real people */
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}

.book__foot{
  display:flex; flex-wrap:wrap; gap:18px; align-items:center; justify-content:space-between;
  margin-top:30px; padding-top:22px; border-top:var(--rule);
}
.book__terms{margin:0; max-width:46ch}
.book__error{
  margin:18px 0 0; padding:13px 16px; border:1px solid var(--pink-hot);
  background:rgba(249,143,192,.09); color:var(--bone);
  font-family:var(--data); font-size:13px;
}
.book__error a{color:var(--pink); border-bottom:1px solid rgba(253,194,219,.4)}

.book__done{display:none; text-align:center; padding:38px 0; max-width:52ch; margin:0 auto}
.book__done .eyebrow{margin-bottom:12px}
.book__done .h-md{margin:0 0 12px}
.book.sent .book__form{display:none}
.book.sent .book__done{display:block}

@media(max-width:640px){ .grid2{grid-template-columns:1fr} }
