/* ============================================================
   Shared contact-form primitives — used by the contact page's
   own form and the homepage's "Let's talk" form. One definition
   so editing a field style updates both instances at once.
   ============================================================ */

.con-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.con-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Column count is a variable, not a modifier class, because the two forms
   legitimately differ in LAYOUT while sharing every field style: the contact
   page's form sits in a 3fr/2fr grid beside the info column so it stays 2-up,
   while the homepage's runs full width and fits 3. Set `--cols: 3` on the row
   that wants three; everything else inherits the 2-up default. */
.con-field-row {
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), 1fr);
  gap: 20px;
}

.con-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #F4F4F4;
}

.con-required {
  color: #00BDFF;
  margin-left: 3px;
}

/* Fields are filled, hard-cornered boxes — same construction as the
   positions/careers card tiles (2px cyan edge on a lifted panel), at field
   scale. This replaced a transparent field with a 1px underline at 20%
   opacity, which on this section's #0d1012 ground was effectively invisible:
   there was no way to tell where you were meant to type until you clicked.
   The fill does the legibility work, the border does brand identity.

   SQUARE CORNERS ARE DELIBERATE — the teardrop radius is reserved for
   actions (buttons). If fields wear it too, the button stops reading as the
   thing you click. See docs/brand.md.

   Height floor: 11px vertical padding puts these at ~45px, just above the
   ~44px minimum touch target. Don't tighten further without accounting for
   that — it's the reason this isn't shorter. */
.con-input,
.con-textarea {
  background: #202124;
  border: 2px solid rgba(0,189,255,0.40);
  border-radius: 0;
  color: #F4F4F4;
  font-family: 'Libre Franklin', sans-serif;
  font-size: 16px;
  padding: 11px 14px;
  outline: none;
  transition: border-color 0.2s, background-color 0.2s;
  width: 100%;
  -webkit-appearance: none;
}

.con-input:hover,
.con-textarea:hover {
  border-color: rgba(0,189,255,0.6);
}

/* Border to full cyan + a fill lift. Deliberately not a border-WIDTH change:
   that would shift the text inside the box by 1px on focus. */
.con-input:focus,
.con-textarea:focus {
  border-color: #00BDFF;
  background: #26282b;
}

.con-input::placeholder,
.con-textarea::placeholder { color: rgba(244,244,244,0.2); }

.con-textarea {
  resize: vertical;
  min-height: 104px;
}

/* Submit = action button: white teardrop, no arrow (arrows mean "leaves
   the page" sitewide). */
.con-submit {
  /* Fill + hover come from the global .btn.btn-white; this only owns layout. */
  width: 100%;
  justify-content: center;
  margin-top: 8px;
  min-width: 186px; /* holds width across "Send Message" <-> "Sending…" */
}

.con-submit.is-sending { cursor: progress; }

/* Spinner: a rotating gap in an otherwise-solid ring, dark-on-white to match
   the button's own text color. Same construction as the apply modal's — both
   submits should read identically. Hidden until .is-sending so the resting
   button never carries the extra 10px gap from .btn's flex layout. */
.con-submit__spinner {
  display: none;
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid rgba(22,23,25,0.25);
  border-top-color: #161719;
}
.con-submit.is-sending .con-submit__spinner {
  display: inline-block;
  animation: conSpin 0.7s linear infinite;
}
@keyframes conSpin { to { transform: rotate(360deg); } }

/* The dimmed, locked field list is what actually makes "something is
   happening" read at a glance — the disabled button alone doesn't (S148).
   Dims the fields only, never the button: the spinner has to stay at full
   contrast, and .con-form-actions holds both. */
.con-field,
.con-field-row,
.con-captcha { transition: opacity 0.25s ease; }

.con-form.is-sending .con-field,
.con-form.is-sending .con-field-row,
.con-form.is-sending .con-captcha {
  opacity: 0.45;
  pointer-events: none;
}

.con-error {
  display: none;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #FF8C7A;
  padding: 16px 0;
  border-top: 1px solid rgba(255,140,122,0.25);
  margin-top: 16px;
}
.con-error.is-shown { display: block; }

.con-captcha { margin-top: 8px; }

/* Captcha and submit on one row, button right-aligned to the form's edge.
   Keeps the fixed ~300px reCAPTCHA widget from sitting alone on the left, and
   sizes the button to its label instead of stretching it into a slab. Wraps on
   its own when the two no longer fit. */
.con-form-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 4px;
}
/* .con-submit is width:100% for stacked layouts; in this row it sizes to
   its content. */
.con-form-actions .con-submit {
  width: auto;
  margin-top: 0;
}

/* Honeypot — moved off-canvas rather than display:none so bots that skip
   invisible fields still see it as a "real" input. */
.con-hp {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

@media (max-width: 600px) {
  .con-field-row { grid-template-columns: 1fr; }
  /* Stacked under the captcha, the button goes full width for thumb reach. */
  .con-form-actions .con-submit { width: 100%; }
}

/* ============================================================
   Success modal — the confirmation for BOTH contact forms.

   Deliberately the same construction as the apply modal's success state
   (cyan-ruled dark panel, cyan ring, checkmark that draws itself in after
   the badge pops, Anton heading, ghost teardrop dismiss): submitting a
   contact form and submitting an application should confirm identically.

   It's a modal rather than an inline block for a layout reason, not a
   decorative one. Swapping a ~600px-tall form for a short confirmation
   collapses the section under the reader and throws the viewport somewhere
   unintended — the page equivalent of the scroll bug fixed in S148. An
   overlay leaves the page geometry untouched.

   Stacked (mark above heading) where the apply modal sits side-by-side:
   that change was made in S149 because its FIXED 90vh shell stranded a
   stacked block in empty space. This panel hugs its content, so there is no
   empty space to strand in, and stacked survives "Message Received." at
   display size without wrapping into the ring.

   Markup is injected by js/contact.js, so it is not duplicated across
   index.html and contact.html.
   ============================================================ */
.cfm-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0,0,0,0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  /* visibility, not just opacity: an opacity:0 panel still holds its place in
     the tab order and the accessibility tree, so a keyboard user could tab
     into an invisible dialog. Transitioned so it stays visible for the fade
     out rather than vanishing on the first frame. */
  visibility: hidden;
  transition: opacity 0.35s ease, visibility 0.35s ease;
}

.cfm-backdrop.is-open {
  opacity: 1;
  pointer-events: all;
  visibility: visible;
}

.cfm-shell {
  position: relative;
  width: 100%;
  max-width: 600px;
  background: #0d1012;
  border-top: 2px solid #00BDFF;
  padding: 56px 48px 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 24px;
  transform: translateY(28px) scale(0.985);
  transition: transform 0.38s cubic-bezier(0.22, 1, 0.36, 1);
}

.cfm-backdrop.is-open .cfm-shell { transform: none; }

.cfm-close {
  position: absolute;
  top: 16px;
  right: 16px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  color: rgba(244,244,244,0.45);
  transition: color 0.2s ease;
  line-height: 0;
}

.cfm-close:hover { color: #00BDFF; }

.cfm-close svg {
  display: block;
  width: 24px;
  height: 24px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
}

.cfm-mark {
  width: 76px;
  height: 76px;
  flex-shrink: 0;
  border: 2px solid #00BDFF;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #00BDFF;
}

/* Badge pops in first (spring overshoot), then the checkmark draws itself —
   two small motions reading as one deliberate "confirmed" beat rather than
   everything fading in at once. */
.cfm-backdrop.is-open .cfm-mark {
  animation: cfmMarkPop 0.4s 0.12s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

.cfm-mark svg {
  width: 36px;
  height: 36px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.cfm-mark svg polyline {
  stroke-dasharray: 32;
  stroke-dashoffset: 32;
}
.cfm-backdrop.is-open .cfm-mark svg polyline {
  animation: cfmCheckDraw 0.45s 0.28s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}

@keyframes cfmMarkPop {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes cfmCheckDraw {
  to { stroke-dashoffset: 0; }
}

.cfm-heading {
  font-family: 'Anton', sans-serif;
  font-weight: 400;
  font-size: clamp(32px, 6vw, 48px);
  text-transform: uppercase;
  color: #F4F4F4;
  line-height: 1;
  margin: 0;
}

.cfm-sub {
  font-family: 'Libre Franklin', sans-serif;
  font-size: 17.5px;
  font-weight: 300;
  color: #DADCE0;
  line-height: 1.65;
  max-width: 420px;
  margin: 0;
}

/* Ghost teardrop, not the white primary: dismissing a confirmation is the
   least important thing on this panel. */
.cfm-dismiss {
  background: none;
  border: 1px solid rgba(244,244,244,0.25);
  color: rgba(244,244,244,0.65);
  cursor: pointer;
  font-family: 'Anton', sans-serif;
  font-weight: 400;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 12px 28px;
  border-radius: 0 20px 20px 20px;
  transition: border-color 0.2s ease, color 0.2s ease;
  margin-top: 4px;
}

.cfm-dismiss:hover {
  border-color: #00BDFF;
  color: #00BDFF;
}

@media (max-width: 600px) {
  .cfm-shell { padding: 48px 26px 36px; gap: 20px; }
  .cfm-mark { width: 62px; height: 62px; }
  .cfm-mark svg { width: 29px; height: 29px; }
}

@media (prefers-reduced-motion: reduce) {
  .con-submit.is-sending .con-submit__spinner { animation: none; }
  .cfm-backdrop, .cfm-shell { transition: none; }
  .cfm-backdrop.is-open .cfm-mark { animation: none; }
  .cfm-mark svg polyline { stroke-dasharray: none; stroke-dashoffset: 0; }
  .cfm-backdrop.is-open .cfm-mark svg polyline { animation: none; }
}
