/* Contact modal — Figma RJ-Home-Page-2026, node 395:88051 ("Contact Form").
   Values are the measured ones from the file. The panel there sits at ~0.96
   scale, which is why sizes land on fractions (30.743px = 32 × 0.9607).
   Markup is injected by contact.js; any [data-contact-open] element opens it.
   The dialog is .contact-modal, not .contact: index.html already uses .contact
   for its "elsewhere" links block.

   Vertical rhythm — three values only, all from the file:
     8        inside a block   (question → chips, submit → email line)
     23.057   between siblings (group → group, field → field, fields → submit)
     34.586   between sections (title → questions, questions → fields; 36 × 0.9607)
   The message box is the one elastic element: it absorbs viewport height so
   the panel fits a 794px-tall window without scrolling (see textarea rule).

   Motion — the Figma file has no prototype motion for this panel, so every
   duration, easing and offset below is a deliberate choice. Everything is
   transform/opacity only. Base rules describe the CLOSED state and carry the
   exit transition; .is-open rules carry the entrance; .is-closing (set by JS
   with the removal of .is-open) pins the content so the card leaves as one
   object. Keep the reduced-motion block last. */

.contact-modal {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #000;
  overflow: hidden;
}
.contact-modal::backdrop { background: transparent; }
.contact-modal [hidden] { display: none !important; }

/* Full-bleed page surface behind the panel (node 395:88216).
   Open: leads the panel by 40ms. Close: ends with the panel (220ms). */
.contact-overlay {
  position: absolute;
  inset: 0;
  background: var(--bg, #fcfcfc);
  opacity: 0;
  transition: opacity 220ms cubic-bezier(0.4, 0, 0.7, 0.2);
}
.contact-modal.is-open .contact-overlay {
  opacity: 1;
  transition: opacity 320ms cubic-bezier(0.2, 0, 0, 1);
}

/* Everything right of the panel — reserved for the (interactive) illustration. */
.contact-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: calc(18.24px + 427.522px);
}

/* Panel (node 395:88247): 427.522 × 762.815 at (18.24, 14.49) in a 794px-tall
   frame, so it keeps 16.7px clear at the bottom. The bottom padding (28.35)
   lives on .contact-actions so that block can stick to the bottom edge on
   viewports too short for the whole form.
   Motion: the panel lives in the bottom-left of the page, so it grows out of
   that corner — 2% small, 36px low, 20px left. Base = closed state + the exit
   (quick ease-in; transform and opacity both land at 220ms, which is what
   close() in contact.js waits for). */
.contact-panel {
  position: absolute;
  top: 14.49px;
  bottom: 16.7px;
  left: 18.24px;
  width: 427.522px;
  max-width: calc(100% - 36.48px);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  padding: 47.88px 34.59px 0 32.66px;
  background: #fff;
  border: 0.961px solid #efefef;
  border-radius: 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  transform-origin: 20% 100%;
  opacity: 0;
  transform: translate(-20px, 36px) scale(0.98);
  transition:
    transform 220ms cubic-bezier(0.4, 0, 0.7, 0.2),
    opacity   220ms cubic-bezier(0.4, 0, 0.7, 0.2);
}

/* Open: a spring (ζ = 0.8) sampled into linear() — 95% of the travel by
   ~276ms, a 1.5% (≈0.5px) overshoot around 420ms, at rest at 600ms. Opacity
   ramps fast so the card is solid while it is still moving. The first
   transition line is the fallback for browsers without linear() (ease-out
   quint, no overshoot); the second overrides it where supported. */
.contact-modal.is-open .contact-panel {
  opacity: 1;
  transform: none;
  transition:
    transform 600ms cubic-bezier(0.22, 1, 0.36, 1) 40ms,
    opacity   240ms cubic-bezier(0.2, 0, 0, 1) 40ms;
  transition:
    transform 600ms linear(0, 0.057 5%, 0.188 10%, 0.344 15%, 0.498 20%, 0.635 25%, 0.749 30%, 0.837 35%, 0.903 40%, 0.956 46%, 0.988 52%, 1.009 60%, 1.015 70%, 1.012 80%, 1.008 90%, 1 100%) 40ms,
    opacity   240ms cubic-bezier(0.2, 0, 0, 1) 40ms;
}

/* <dialog> hands initial focus to the scrollable panel; no ring on the whole card. */
.contact-panel:focus { outline: none; }

/* Form view. flex:1 lets the first group's margin-top:auto hand any surplus
   panel height to the title seam (Figma's bottom-anchored composition); it is
   0 until the message box has reached its full 139.305px (viewports ≥ ~849px). */
.contact-body {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}

/* Content stagger — title, the three chip groups, then the fields rise 12px
   into place a beat behind the panel, 40ms apart, on the same spring; the
   action block only fades. Base = closed state, no transition (the exit is
   the panel's alone — .is-closing pins these visible while it leaves). */
.contact-body > .contact-title,
.contact-body > .contact-services,
.contact-fields {
  opacity: 0;
  transform: translateY(12px);
  transition: none;
}
.contact-actions {
  opacity: 0;
  transition: none;
}
.contact-modal.is-closing .contact-body > .contact-title,
.contact-modal.is-closing .contact-body > .contact-services,
.contact-modal.is-closing .contact-fields,
.contact-modal.is-closing .contact-actions {
  opacity: 1;
  transform: none;
}
.contact-modal.is-open .contact-body > .contact-title,
.contact-modal.is-open .contact-body > .contact-services,
.contact-modal.is-open .contact-fields {
  opacity: 1;
  transform: none;
  transition:
    transform 520ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity   300ms cubic-bezier(0.2, 0, 0, 1);
  transition:
    transform 520ms linear(0, 0.057 5%, 0.188 10%, 0.344 15%, 0.498 20%, 0.635 25%, 0.749 30%, 0.837 35%, 0.903 40%, 0.956 46%, 0.988 52%, 1.009 60%, 1.015 70%, 1.012 80%, 1.008 90%, 1 100%),
    opacity   300ms cubic-bezier(0.2, 0, 0, 1);
}
.contact-modal.is-open .contact-actions {
  opacity: 1;
  transition: opacity 300ms cubic-bezier(0.2, 0, 0, 1);
}
.contact-modal.is-open .contact-body > .contact-title                   { transition-delay: 100ms; }
.contact-modal.is-open .contact-body > .contact-services:nth-of-type(1) { transition-delay: 140ms; }
.contact-modal.is-open .contact-body > .contact-services:nth-of-type(2) { transition-delay: 180ms; }
.contact-modal.is-open .contact-body > .contact-services:nth-of-type(3) { transition-delay: 220ms; }
.contact-modal.is-open .contact-fields,
.contact-modal.is-open .contact-actions                                 { transition-delay: 260ms; }

/* Close pill: fades in last on open, rides the card out on close. */
.contact-close {
  position: absolute;
  top: 16px;
  right: 16px;
  padding: 7px 8px;
  border: 0;
  border-radius: 120px;
  background: #f2f2f2;
  color: #000;
  font-family: "Geist Mono", "SF Mono", Menlo, monospace;
  font-size: 9px;
  font-weight: 400;
  line-height: 0.87;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transition: background 200ms ease;
}
.contact-modal.is-closing .contact-close { opacity: 1; }
.contact-modal.is-open .contact-close {
  opacity: 1;
  transition: background 200ms ease, opacity 240ms cubic-bezier(0.2, 0, 0, 1) 300ms;
}
.contact-close:hover { animation: contactAccentCycle 1.8s steps(1, end) infinite; }

/* Sheet grab handle — mobile only (see media query). */
.contact-grab { display: none; }

/* "hi! i'm excited to hear from you." (395:88248). Section step below. */
.contact-title {
  width: 256.843px;
  max-width: 100%;
  margin: 0 0 34.586px;
  font-family: "aktiv-grotesk", "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 30.743px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -1.5372px;
}

/* Question + biscuits (395:88920). All three groups share this anatomy:
   legend row → 8 → chips. The fieldset spans the full content width so the
   hint fits beside the question; the services chips are capped at Figma's
   256.843 so they keep the 3 + 3 wrap. */
.contact-services {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 358.35px;
  max-width: 100%;
  margin: auto 0 0;
  padding: 0;
  border: 0;
}
.contact-services.contact-group { margin-top: 23.057px; }
.contact-services .contact-chips { max-width: 256.843px; }
.contact-group .contact-chips { max-width: none; }
.contact-group .contact-chip { width: auto; }

/* The float is load-bearing: a floated <legend> is not the fieldset's
   "rendered legend", so it lays out as an ordinary flex item. The legend is
   itself a flex row so the hint sits on the question's baseline, and wraps
   under it (row-gap 8) on screens narrower than ~300px of content. */
.contact-services legend {
  float: left;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 0;
  font-family: "aktiv-grotesk", "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 19.214px;
  font-weight: 500;
  line-height: 1.13;
  letter-spacing: -0.5764px;
}

/* One meta voice for every secondary line — hint, floating field label,
   status, email line. Not in the Figma frame; it is the site's Geist Mono
   9px uppercase used in the top nav. (For a lowercase hint, drop
   text-transform on .contact-hint only.) */
.contact-hint,
.contact-field-label,
.contact-status,
.contact-alt {
  margin: 0;
  color: var(--ink-soft, #5a5a5a);
  font-family: "Geist Mono", "SF Mono", Menlo, monospace;
  font-size: 9px;
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: uppercase;
}

.contact-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.contact-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 76.538px;
  height: 28px;
  padding: 6px 8px;
  border: 1px solid #efefef;
  border-radius: 99.744px;
  background: #fff;
  color: #000;
  font-family: "aktiv-grotesk", "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 11.529px;
  font-weight: 500;
  line-height: 1.2; /* Figma 1.4 overflows the 14px content area of a 28px chip */
  letter-spacing: -0.2306px;
  white-space: nowrap;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}
.contact-chip[data-service="brand identity"] { width: 88px; }
.contact-chip[data-service="web design"]     { color: #1f1f1f; }

/* Selected — not in the Figma frame: each biscuit fills with its colour
   from the first version of the design (395:88263). "other" and the
   single-pick groups have no brand colour, so they go black. */
.contact-chip[aria-pressed="true"] { border-color: transparent; }
.contact-chip[data-service="brand identity"][aria-pressed="true"] { background: #10baff; }
.contact-chip[data-service="illustration"][aria-pressed="true"]   { background: #ff5ac4; }
.contact-chip[data-service="product"][aria-pressed="true"]        { background: #ff5d38; }
.contact-chip[data-service="web design"][aria-pressed="true"]     { background: #000; color: #fe32b3; }
.contact-chip[data-service="motion"][aria-pressed="true"]         { background: #2db4ef; }
.contact-chip[data-service="other"][aria-pressed="true"],
.contact-group .contact-chip[aria-pressed="true"]                 { background: #000; color: #fff; }

/* Fields + submit (395:88249). Section step above; the fields → submit gap
   is the action block's own top padding (see .contact-actions). */
.contact-form {
  display: flex;
  flex-direction: column;
  width: 358.35px;
  max-width: 100%;
  margin-top: 34.586px;
}
.contact-fields {
  display: flex;
  flex-direction: column;
  gap: 23.057px;
}
.contact-field {
  position: relative;
  display: block;
}
.contact-input {
  display: block;
  box-sizing: border-box;
  width: 100%;
  height: 37.468px;
  margin: 0;
  padding: 9.607px;
  border: 0;
  border-bottom: 0.961px solid #d7d7d7;
  border-radius: 0;
  background: transparent;
  color: #000;
  font-family: "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 11.529px;
  font-weight: 500;
  line-height: 1.13;
  letter-spacing: -0.2306px;
  outline: none;
  transition: border-color 150ms ease;
}

/* The message box is the one elastic element. Fixed stack (borders, padding,
   title, three groups, name + email, action block and every gap) = 675.055;
   the panel's top + bottom insets = 31.19; 3px of slack → 709.245. So it is
   84.755px (5 lines) at a 794px-tall viewport, Figma's 139.305 from ~849px,
   and never less than 4 lines. Recompute the constant if any value above
   changes. */
textarea.contact-input {
  height: clamp(71.33px, calc(100vh - 709.245px), 139.305px);
  resize: none;
}
.contact-input::placeholder { color: #000; opacity: 1; }
.contact-input:focus { border-bottom-color: #000; }

/* Field name above a filled-in field — not in the Figma frame. Hidden while
   the placeholder shows, so the empty form matches the design. Sits closer
   to its own field's text (~10px) than to the rule above it (14px). */
.contact-field-label {
  position: absolute;
  top: -9px;
  left: 9.607px;
  line-height: 1;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 150ms ease, transform 150ms ease;
  pointer-events: none;
}
.contact-input:not(:placeholder-shown) ~ .contact-field-label {
  opacity: 1;
  transform: none;
}

/* Submit + email line. Sticky to the panel's bottom edge, which only matters
   on viewports too short for the form (e.g. 1366 × 768 laptops); it carries
   the panel's 28.35 bottom padding so the stack is unchanged. */
.contact-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 23.057px 0 28.35px;
  background: #fff;
}

.contact-submit {
  width: 100%;
  height: 38.9px;
  padding: 13.45px 9.607px;
  border: 0;
  border-radius: 5.764px;
  background: #f3f3f3;
  color: #000;
  font-family: "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 13.45px;
  font-weight: 500;
  line-height: 0.87;
  cursor: pointer;
  transition: background 200ms ease;
}
.contact-submit:hover:not(:disabled) {
  color: #0e0e0e;
  animation: contactAccentCycle 1.8s steps(1, end) infinite;
}
.contact-submit:disabled { cursor: default; opacity: 0.6; }

.contact-status { color: inherit; }
.contact-status:empty { display: none; }
/* The error text carries the mailto link, so the email line steps aside and
   the stack keeps its height. */
.contact-status:not(:empty) + .contact-alt { display: none; }
.contact-status a,
.contact-alt a { color: inherit; }

/* Sent view — replaces the form after a successful send. Not in the Figma
   frame; reuses the title, question and pill styles on the sibling step. */
.contact-done {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 23.057px;
  padding-bottom: 28.35px;
}
.contact-done .contact-title { margin: 0; }
.contact-done-title:focus { outline: none; }
.contact-done-text {
  width: 256.843px;
  max-width: 100%;
  margin: 0;
  color: var(--ink-soft, #5a5a5a);
  font-family: "aktiv-grotesk", "Geist", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 19.214px;
  font-weight: 500;
  line-height: 1.13;
  letter-spacing: -0.5764px;
}
.contact-again {
  padding: 7px 8px;
  border: 0;
  border-radius: 120px;
  background: #f2f2f2;
  color: #000;
  font-family: "Geist Mono", "SF Mono", Menlo, monospace;
  font-size: 9px;
  font-weight: 400;
  line-height: 0.87;
  text-transform: uppercase;
  cursor: pointer;
}
.contact-again:hover { animation: contactAccentCycle 1.8s steps(1, end) infinite; }

/* Spam trap — hidden from people, filled in by bots. */
.contact-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-chip:focus-visible,
.contact-submit:focus-visible,
.contact-close:focus-visible,
.contact-again:focus-visible {
  outline: 2px solid #2db4ef;
  outline-offset: 2px;
}

@keyframes contactAccentCycle {
  0%, 100% { background: #FF4F27; }
  33%      { background: #FF64C7; }
  66%      { background: #2DB4EF; }
}

html.contact-lock { overflow: hidden; }

/* Dark theme — not in the Figma file; mirrors the site's dark surfaces. */
[data-theme="dark"] .contact-panel {
  background: #161616;
  border-color: #1f1f1f;
  color: var(--ink, #f2f2f2);
}
[data-theme="dark"] .contact-input { color: var(--ink, #f2f2f2); border-bottom-color: #2a2a2a; }
[data-theme="dark"] .contact-input::placeholder { color: var(--ink, #f2f2f2); }
[data-theme="dark"] .contact-input:focus { border-bottom-color: var(--ink, #f2f2f2); }
[data-theme="dark"] .contact-submit,
[data-theme="dark"] .contact-close,
[data-theme="dark"] .contact-again { background: #1f1f1f; color: var(--ink, #f2f2f2); }
[data-theme="dark"] .contact-chip { background: #161616; border-color: #2a2a2a; color: var(--ink, #f2f2f2); }
[data-theme="dark"] .contact-chip[aria-pressed="true"] { border-color: transparent; color: #000; }
[data-theme="dark"] .contact-chip[data-service="web design"][aria-pressed="true"] { color: #fe32b3; }
[data-theme="dark"] .contact-chip[data-service="other"][aria-pressed="true"],
[data-theme="dark"] .contact-group .contact-chip[aria-pressed="true"] { background: #f2f2f2; color: #000; }
[data-theme="dark"] .contact-actions { background: #161616; }

/* Mobile — not in the Figma file. The panel becomes a bottom sheet that
   slides up (drag the handle down to dismiss); the illustration area is
   dropped. Same rhythm as desktop. The sheet is solid and slides as one
   object (no content stagger — the overlay does the fade), on an ease-out
   with no overshoot. The message box keeps Figma's height: the sheet
   scrolls and submit + email line stay pinned to the bottom. Inputs go to
   16px so iOS Safari doesn't zoom the page on focus. */
@media (max-width: 768px) {
  .contact-art { display: none; }
  .contact-panel {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    max-width: none;
    max-height: calc(100dvh - 24px);
    padding: 48px 16px 0;
    border-bottom: 0;
    border-radius: 12px 12px 0 0;
    transform-origin: 50% 100%;
    opacity: 1;
    transform: translateY(100%);
    transition: transform 300ms cubic-bezier(0.4, 0, 0.7, 0.2);
  }
  .contact-modal.is-open .contact-panel {
    transition: transform 560ms cubic-bezier(0.22, 1, 0.36, 1) 20ms;
  }
  .contact-overlay { transition: opacity 240ms cubic-bezier(0.4, 0, 0.7, 0.2) 60ms; }
  .contact-body > .contact-title,
  .contact-body > .contact-services,
  .contact-fields,
  .contact-actions,
  .contact-close,
  .contact-modal.is-open .contact-body > .contact-title,
  .contact-modal.is-open .contact-body > .contact-services,
  .contact-modal.is-open .contact-fields,
  .contact-modal.is-open .contact-actions,
  .contact-modal.is-open .contact-close {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0ms;
  }
  .contact-modal.is-open .contact-close { transition: background 200ms ease; }
  .contact-grab {
    display: block;
    position: absolute;
    top: 0;
    left: 50%;
    width: 88px;
    height: 28px;
    margin-left: -44px;
    touch-action: none;
    cursor: grab;
  }
  .contact-grab::before {
    content: "";
    position: absolute;
    top: 10px;
    left: 26px;
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: #d7d7d7;
  }
  [data-theme="dark"] .contact-grab::before { background: #2a2a2a; }
  .contact-services { margin-top: 0; }
  .contact-services.contact-group { margin-top: 23.057px; }
  .contact-form { width: 100%; }
  .contact-input { height: auto; font-size: 16px; }
  textarea.contact-input { height: 139.305px; }
  .contact-actions { padding: 23.057px 0 calc(24px + env(safe-area-inset-bottom)); }
  .contact-done { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
}

/* Reduced motion — keep this block last. Every state collapses to a short
   fade in place; it has to repeat the .is-open / .is-closing selectors
   because the entrance transitions live on them. */
@media (prefers-reduced-motion: reduce) {
  .contact-overlay,
  .contact-modal.is-open .contact-overlay {
    transition: opacity 160ms ease;
    transition-delay: 0ms;
  }
  .contact-panel,
  .contact-modal.is-open .contact-panel {
    transform: none;
    transition: opacity 160ms ease;
    transition-delay: 0ms;
  }
  .contact-panel { opacity: 0; }
  .contact-modal.is-open .contact-panel { opacity: 1; }
  .contact-body > .contact-title,
  .contact-body > .contact-services,
  .contact-fields,
  .contact-actions,
  .contact-close,
  .contact-modal.is-open .contact-body > .contact-title,
  .contact-modal.is-open .contact-body > .contact-services,
  .contact-modal.is-open .contact-fields,
  .contact-modal.is-open .contact-actions,
  .contact-modal.is-open .contact-close {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0ms;
  }
  .contact-modal.is-open .contact-close { transition: background 200ms ease; }
  .contact-close:hover,
  .contact-again:hover,
  .contact-submit:hover:not(:disabled) { animation: none; background: #FF64C7; }
}
