/*
 * "Curtain up": the cross-document view transition between the pages that
 * carry the nav (docs/v2-motion/nav-transitions-bios.md §2). Like the rest of
 * the site it travels vertically: the cover rises from the bottom, holds while
 * the dog pops on, and leaves through the top. Loaded only with SiteNav, so
 * only those pages opt in. Without JS, or with reduced motion, the UA's short
 * cross-fade runs instead; browsers without cross-document view transitions
 * simply navigate.
 *
 * Timeline (ms; CURTAIN in src/scripts/page-transition.ts), pure CSS, never
 * waiting on script: the cover rises 0–300 (screen covered by ~145) and the
 * old snapshot is swapped for the new page at 200; the dog pops 80–320; the
 * cover leaves through the top 380–600. Both intro pages pose their first
 * frame from inline gates before the first render, so there is nothing to
 * wait for; their clocks are held until the cover has gone. Percentages are
 * of 600.
 */
@view-transition { navigation: auto; }

.page-curtain { display: none; }
html:active-view-transition-type(dd-curtain) .page-curtain {
  --hem: 28px; --wave: 260px; --trim: 10px; --bleed: 10lvh; --mark: clamp(5.5rem, 14vmin, 9rem);
  --curtain: var(--deep-ink); --curtain-trim: var(--hot-pink);
  display: block; position: fixed; z-index: 2147483000; inset: 0 0 auto; height: 100lvh; pointer-events: none;
  view-transition-name: dd-curtain;
}
/* The cover is the colour each page's intro opens on: the hero's purple void,
   the team stage's deep ink (continuous with the nav). */
html:active-view-transition-type(dd-curtain) .page-curtain--home { --curtain: var(--purple); --curtain-trim: var(--field-pink); }
@media (max-width: 699px) {
  html:active-view-transition-type(dd-curtain) .page-curtain { --hem: 18px; --wave: 150px; --trim: 7px; --mark: 22vmin; }
}
/* Liquid edges top and bottom (the hero sky flood's edge: 14px / 260px, phone
   9px / 150px), each with a flat pink trim showing beyond it. The body bleeds
   past the screen at both ends (captured as overflow), so its overshoot on the
   way up and its wind-up on the way out never open a gap. */
html:active-view-transition-type(dd-curtain) .page-curtain::before,
html:active-view-transition-type(dd-curtain) .page-curtain::after {
  content: ''; position: absolute; left: 0; right: 0;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 260 28' preserveAspectRatio='none'%3E%3Cpath d='M0 28V14C21.22 6.82 41.48 0 65 0S108.78 6.82 130 14 171.48 28 195 28 238.78 21.18 260 14V28Z'/%3E%3C/svg%3E") left top / var(--wave) var(--hem) repeat-x, linear-gradient(#000 0 0) center / 100% calc(100% - 2 * var(--hem) + 2px) no-repeat, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 260 28' preserveAspectRatio='none'%3E%3Cpath d='M0 0V14C21.22 21.18 41.48 28 65 28S108.78 21.18 130 14 171.48 0 195 0 238.78 6.82 260 14V0Z'/%3E%3C/svg%3E") left bottom / var(--wave) var(--hem) repeat-x;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 260 28' preserveAspectRatio='none'%3E%3Cpath d='M0 28V14C21.22 6.82 41.48 0 65 0S108.78 6.82 130 14 171.48 28 195 28 238.78 21.18 260 14V28Z'/%3E%3C/svg%3E") left top / var(--wave) var(--hem) repeat-x, linear-gradient(#000 0 0) center / 100% calc(100% - 2 * var(--hem) + 2px) no-repeat, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 260 28' preserveAspectRatio='none'%3E%3Cpath d='M0 0V14C21.22 21.18 41.48 28 65 28S108.78 21.18 130 14 171.48 0 195 0 238.78 6.82 260 14V0Z'/%3E%3C/svg%3E") left bottom / var(--wave) var(--hem) repeat-x;
}
html:active-view-transition-type(dd-curtain) .page-curtain::before { inset: calc(-1 * (var(--bleed) + var(--hem) + var(--trim))) 0; background: var(--curtain-trim); }
html:active-view-transition-type(dd-curtain) .page-curtain::after { inset: calc(-1 * (var(--bleed) + var(--hem))) 0; background: var(--curtain); }
/* The dog shares the cover's box, so both travel together; it sits at the
   centre of the screen and is captured as its own layer. */
html:active-view-transition-type(dd-curtain) .page-curtain-mark {
  position: absolute; z-index: 1; inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 41.3 46.11'%3E%3Cpath fill='%23f1e9e9' d='M38.34,19.29c.36-5.61.11-13.43-.35-16.64-.18-2.53-2.1-3.68-3.94-1.49-2.09,2.47-3.53,7.71-6.05,9.21-2.07,1.16-1.31-1.29-1.16-3.17.13-1.17-.01-3.17-1.44-2.36-1.87,1.37-3.28,4.58-4.45,6.65-3.51,6.64-9.4,5.36-15.26,7.62C.42,21.08-.58,27.27.26,32.24c.25,1.72.72,3.64,1.49,5.17.19.35.35.49.46.41.63-.44.11-5.3,1.16-2.21.33.97,3.62,8.88,3.19,5.25-.11-.92.03-2.05.36-1.19.76,1.99,2.46,4.75,4.13,5.6,1,.51-1-2.34-1.05-2.88-.11-.51.13-.28.65.39.83,1.13,3.13,3.03,4.53,3.3,1.3.23-1.04-1.67-1.22-2.09-.36-.85,1.52.64,2.36.96,2.05.79,3.93,1.04,6.24.58.45-.08,1.76-.36,3.03-.9,1.78-.76,2.57-1.38,3.28-2.33s.51-1.36.8-1.42c.8-.17-.39,4.91,1.75,1.03,1.25-2.26-.03-4.37.66-6.05.22-.53.47.88.65,2.11.58,4.08,2.57-2.5,2.48-6.94-.02-.9.49.49.68,1.69.35,2.58,1.34.88,1.64-.32.88-3.76.69-8.66.79-12.93v-.21Z'/%3E%3Cpath fill='%23291f44' d='M11.04,17.86c-.46-1.38-.7-3.67.39-4.46,1.39-.91,3.19.18,4.62.52,6.06,1.89,12.14,3.92,18.21,5.87,1.98.75,4.36,1.11,6.05,2.47.7.63,1.12,1.77.94,2.87-.3,1.79-1.7,2.41-2.51.81-.77-1.56-2.36-2.67-3.96-2.29-1.38.38-2.22,2.19-3.59,3.3-.7.61-1.49,1.12-2.33,1.38-3.28,1.07-5.85-2.2-7.13-5.28-1.16-2.83-2.02-2.49-4.18-1.43-2.79,1.27-5.58-.61-6.48-3.65l-.04-.12ZM13.45,18.52c-.29-.39-1.24-1.74-1.07-.42.2.89,1.44,3.09,2.41,2.41.07-.1.08-.24.03-.38-.26-.59-.94-1.04-1.3-1.52l-.07-.08ZM23.72,23.01c-.95-.62-.26,1.09.01,1.46.56,1.01,1.15,1.71,2.1,2.2.31.16.86.3,1.01-.15.08-.62-.76-1-1.11-1.37-.66-.56-1.42-1.48-1.95-2.08l-.07-.06Z'/%3E%3C/svg%3E") no-repeat;
  background-size: var(--mark) auto;
  background-position: 50% calc(50lvh - var(--mark) * .5583);
  view-transition-name: dd-curtain-mark;
}

/* Up from the bottom, dog, out through the top: one 600ms pass. */
html:active-view-transition-type(dd-curtain)::view-transition-group(dd-curtain),
html:active-view-transition-type(dd-curtain)::view-transition-group(dd-curtain-mark) { animation: dd-curtain-in 600ms both; }
html:active-view-transition-type(dd-curtain)::view-transition-new(dd-curtain) { animation: none; }
html:active-view-transition-type(dd-curtain)::view-transition-new(dd-curtain-mark) { transform-origin: 50% 50lvh; animation: dd-curtain-mark-in 600ms both; }
html:active-view-transition-type(dd-curtain)::view-transition-old(root) { animation: dd-curtain-old 600ms both; }
html:active-view-transition-type(dd-curtain)::view-transition-new(root) { animation: dd-curtain-new 600ms both; }

/* Keyframe easings are the --dd-* curves inlined (navigation.css): var() is
   not resolved for timing functions inside @keyframes here. The cover travels
   120lvh: the screen plus its bleed, hems and trims. It rises in on dd.settle
   (fast off the mark for instant feedback, 2.5% overshoot into the bleed) and
   leaves on dd.exit (a small wind-up into the bottom bleed, then away). */
@keyframes dd-curtain-in {
  0% { transform: translateY(120lvh); animation-timing-function: linear(0, 0.0761 2%, 0.179 4.83%, 0.248 6.83%, 0.34 9.67%, 0.4014 11.67%, 0.4826 14.5%, 0.5363 16.5%, 0.6068 19.33%, 0.6751 22.33%, 0.7165 24.33%, 0.8017 29%, 0.836 31.17%, 0.876 34%, 0.9324 38.83%, 0.968 42.83%, 0.998 47.5%, 1.0147 51.5%, 1.0242 56.17%, 1.0249 60.17%, 1.0047 87.33%, 1); }
  50% { transform: translateY(0); animation-timing-function: linear; }
  63.333% { transform: translateY(0); animation-timing-function: linear(0, -0.0062 7.5%, -0.0141 11.33%, -0.0452 22.5%, -0.051 28.33%, -0.0471 31.5%, -0.0335 35%, -0.0132 38.17%, 0.0191 41.83%, 0.0614 45.67%, 0.1276 50.67%, 0.1976 55.33%, 0.293 61.17%, 0.3707 65.67%, 0.5444 75.33%, 1); }
  100% { transform: translateY(-120lvh); }
}
/* The dog pops on (80–320ms), then squashes in the wind-up and stretches as
   the cover whips it away. */
@keyframes dd-curtain-mark-in {
  0%, 13.333% { transform: scale(0) rotate(-16deg); animation-timing-function: linear(0, 0.2124 3.83%, 0.4107 7.5%, 0.5047 9.33%, 0.6555 12.5%, 0.7136 13.83%, 0.788 15.67%, 0.8376 17%, 0.9049 19%, 0.9728 21.33%, 1.0062 22.67%, 1.0356 24%, 1.0702 25.83%, 1.0977 27.67%, 1.1134 29%, 1.1323 31.33%, 1.1404 33.33%, 1.1412 35.33%, 1.1325 38.33%, 1.1144 42%, 1.0973 44.67%, 1.0244 54%, 0.9981 57.83%, 0.9792 61.67%, 0.971 64.83%, 0.97 68%, 0.9935 88.17%, 1); }
  53.333% { transform: none; animation-timing-function: linear; }
  63.333% { transform: none; }
  74.333% { transform: scale(1.07, .93); }
  100% { transform: scale(.9, 1.16); }
}
@keyframes dd-curtain-old { 0%, 33.333% { opacity: 1; } 33.334%, 100% { opacity: 0; } }
@keyframes dd-curtain-new { 0%, 33.333% { opacity: 0; } 33.334%, 100% { opacity: 1; } }
/* One flowing composition, with the decorative hand anchored to the message. */
.contact.contact--purple { background:var(--purple); color:var(--cream); }
.contact--purple .contact-title-art svg [fill]:not([fill="none"]) { fill:var(--cream); }
.contact.contact--purple .button { background:var(--hot-pink); color:var(--white); } /* white, not cream: 4.6:1 on hot pink (WCAG AA) */
.contact.contact--purple .button:hover { background:var(--cream); color:var(--purple); }
.contact.contact--purple .form-status { color:var(--cream); }
.contact.section-screen { min-block-size: var(--screen-block); padding: max(calc(var(--nav-height) + 1.5rem),12.5dvh) 0 3dvh; overflow: clip; }
.contact .contact-title-art { position: relative; z-index: 6; display: flex; align-items: center; gap: 4%; width: min(56%,55rem); margin: 0 auto; overflow: visible; }
.contact .contact-title-art > div { position: static; display: block; }
.contact .contact-title-art .contact-title-ready { width: 40.6%; }
.contact .contact-title-art .contact-title-fearless { width: 55.4%; }
.contact .contact-form { position: relative; z-index: auto; width: min(34%,30rem); margin: clamp(2rem,5dvh,3.5rem) 0 0 53%; padding: 0; }
.contact .form-intro { margin: 0 0 1.25rem; font-size: 1.0625rem; font-weight: 500; line-height: 1.5; }
.contact .contact-intro-break { display: inline; }
.contact .field { margin-bottom: 1rem; }
.contact .field-message { margin-bottom: 0; position: relative; z-index: 3; isolation: isolate; }
/* Retain accessible field names without a visible label row or reserved gap. */
.contact .field label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.contact .field input { height: 3rem; }
.contact .field textarea { position: relative; z-index: 1; height: clamp(7rem,16dvh,9rem); padding: .9rem 1rem; resize: vertical; }
.contact .field input,.contact .field textarea { border: 2px solid transparent; border-radius: .9rem; background: var(--cream); color: var(--purple); font-size: 1rem; font-weight: 400; line-height: 1.4; box-shadow: none; }
.contact .field input { padding-inline: 1rem; }
.contact .field input::placeholder,.contact .field textarea::placeholder { color: var(--purple); opacity: .8; font-weight: 400; }
.contact .field input:focus,.contact .field textarea:focus { border-color: var(--purple); outline: none; box-shadow: 0 0 0 3px var(--field-pink); }
.contact .field input:focus-visible,.contact .field textarea:focus-visible { outline: 2px solid var(--cream); outline-offset: 4px; }
.contact .field [aria-invalid='true'] { border-color: var(--purple); }
.contact .field-error { position: relative; display: block; inset: auto; font-size: .875rem; line-height: 1.4; color: var(--cream); padding: .35rem .25rem 0; }
.contact .field-error:empty { display: none; }
.contact .field label,.contact .field-error,.contact .form-intro { color: #fff; }
.contact .form-footer { margin-top: 1.25rem; grid-template-columns: minmax(0,1fr) auto; }
.contact .button { width: 10rem; min-height: 3rem; font-size: 1rem; }
.contact .form-intro,.contact .field:not(.field-message),.contact .form-footer { position: relative; z-index: 6; }
.contact .field-message .field-error { z-index: 7; }
.contact-hand-anchor { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.contact .contact-hand { position: absolute; z-index: auto; pointer-events: none; }
.contact .contact-hand-mobile { display: none; }
.contact .contact-hand-desktop { --hand-height: min(67dvh,43.5rem); display: block; height: var(--hand-height); width: auto; aspect-ratio: 552.164/696.73; left: auto; right: calc(100% + clamp(1.5rem,3vw,3.5rem)); bottom: auto; top: calc(100% - var(--hand-height) * .7); }
.contact .contact-hand-desktop .contact-hand-composite { position: static; width: 100%; height: 100%; }
.contact .contact-hand-stage .contact-hand-desktop { top: auto; bottom: -1px; left: calc(49% - var(--hand-height) * .79252 - clamp(1.5rem,3vw,3.5rem)); right: auto; }

@media (max-width:1100px) and (orientation:portrait) {
  .contact .contact-hand-stage { display: none; }
  .contact.section-screen { padding-top: calc(var(--nav-height) + 1.5rem); padding-bottom: 3rem; }
  .contact .contact-title-art { display: flex; flex-direction: column; align-items: flex-start; gap: .65rem; width: min(78%,29rem); }
  .contact .contact-title-art .contact-title-ready { width: min(66%,15.85rem); margin-left: 2%; }
  .contact .contact-title-art .contact-title-fearless { width: min(100%,24rem); }
  .contact .contact-form { width: min(80%,29rem); margin: clamp(1.25rem,3dvh,2rem) auto 0; padding: 0; }
  .contact .form-intro { margin: 0 0 .85rem .3rem; font-size: 1rem; }
  .contact .contact-intro-break { display: inline; }
  .contact .field { margin-bottom: 1rem; }
  .contact .field-message { margin-bottom: 0; }
  .contact .field input { height: 2.75rem; padding-inline: 1rem; }
  .contact .field textarea { height: clamp(6.25rem,16dvh,8.5rem); padding: 1rem 1rem 1.75rem; }
  .contact .field input,.contact .field textarea { border-radius: .9rem; font-size: 1rem; }
  .contact .form-footer { margin-top: 1.25rem; }
  .contact .form-footer .button { grid-column: 2; grid-row: 1; }
  .contact .form-status { grid-column: 2; grid-row: 2; max-width: 9.5rem; text-align: right; margin: 0; }
  /* Feedback must stay readable where the decorative phone passes beneath it. */
  .contact .form-status:not(:empty) { padding: .5rem .625rem; border-radius: .55rem; background: var(--cream); color: var(--purple); overflow-wrap: anywhere; }
  .contact .form-footer:has(.form-status:empty) { row-gap: 0; }
  .contact .button { width: 9.5rem; font-size: 1rem; min-height: 2.9rem; }
  .contact .contact-hand-desktop { display: none; }
  .contact .contact-hand-mobile { --hand-height: clamp(15rem,42dvh,24rem); display: block; width: auto; height: var(--hand-height); aspect-ratio: 290/366; left: calc(var(--hand-height) * -.3); right: auto; bottom: auto; top: calc(100% - 1rem - var(--hand-height) * .0738); }
  .contact .field-message:has(.field-error:not(:empty)) .contact-hand-mobile { translate: 0 1.5rem; }
}
@media (min-width:600px) and (min-height:900px) and (orientation:portrait) {
  .contact .contact-hand-mobile { --hand-height: min(52dvh,40rem); }
  /* The arm leaves the frame at the section's foot: the section ends where the arm
     does (≈ .926 of the hand's height below the button, less 5.25rem) instead of a
     full screen, which left a tall tablet's arm hanging mid-air above empty pink. */
  .contact.section-screen { min-block-size: 0; padding-bottom: calc(min(52dvh,40rem) * .926 - 5.25rem); }
}
@media (max-width:430px) and (max-height:650px) {
  .contact.section-screen { padding-top: calc(var(--nav-height) + 1rem); padding-bottom: 1.5rem; }
  .contact .contact-title-art { width: 80%; gap: .4rem; }
  .contact .contact-form { margin-top: 1.25rem; }
  .contact .form-intro { font-size: 1rem; margin-bottom: .6rem; }
  .contact .field { margin-bottom: .85rem; }
  .contact .field-message { margin-bottom: 0; }
  .contact .form-footer { margin-top: .85rem; }
  .contact .contact-hand-mobile { --hand-height: 14rem; }
}
/* Portrait tablets: the title and form grow into the screen, type a step up. */
@media (min-width:600px) and (max-width:1100px) and (orientation:portrait) {
  .contact .contact-title-art { width: min(70%,40rem); }
  .contact .contact-title-art .contact-title-ready { width: min(66%,26rem); }
  .contact .contact-title-art .contact-title-fearless { width: min(100%,40rem); }
  .contact .contact-form { width: min(70%,36rem); }
  .contact .form-intro { font-size: 1.125rem; }
  .contact .field input { height: 3rem; }
  .contact .field input,.contact .field textarea { font-size: 1.0625rem; }
  .contact .button { width: 11rem; min-height: 3.1rem; font-size: 1.0625rem; }
}
/* Phones: title and form span the one gutter (global.css). */
@media (max-width:599px) and (orientation:portrait) {
  .contact .contact-title-art, .contact .contact-form { width: calc(100% - 2 * var(--gutter-mobile)); }
}
/*
 * Contact motion (Phase 2c, docs/v2-motion/contact-footer.md). Every rule is
 * invisible at rest: the composition is the authored one with or without JS.
 */

/* Focus: the brand's hand-drawn underline inside the field. --draw is 0 at
   rest; :focus shows it at once (no JS, reduced motion) and the contact piece
   writes it on and off with GSAP (an inline --draw wins over this rule). */
.contact .contact-form .field :is(input, textarea) {
  background-image: url('/images/derived/manifesto-underline.svg');
  background-repeat: no-repeat;
  background-position: 1rem calc(100% - .42rem);
  background-size: calc((100% - 2rem) * var(--draw, 0)) .3rem;
}
.contact .contact-form .field :is(input, textarea):focus { --draw: 1; }

/* Send squashes on press through the independent `scale` property, so the
   stylesheet's hover lift (transform) keeps working underneath it. */
.contact .button.is-pressing { scale: var(--press-x, 1) var(--press-y, 1); }

/* Hand rig (built at runtime): the rise carries the art; the hand's own box
   clips its bottom edge only while the arm is below its resting line. */
.contact-hand-rig { position: absolute; inset: 0; transform-origin: 50% 100%; }
.contact .contact-hand.is-below-ground { clip-path: inset(-100vh -100vw 0 -100vw); }
.contact-hand-overlay { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }

/* Team page: hold the per-glyph float while the title lands (the piece
   resumes it from the float's midpoint, so the handoff never pops). GSAP owns
   the glyph transforms meanwhile, so the float's translate/rotate are off too
   (GSAP would fold them into an inline transform: motion.css). */
.motion-ready .team-page .contact .contact-title-art.is-landing [data-rig-letter] { animation: none; translate: none !important; rotate: none !important; }
