/* ==========================================================================
   Contact Us — rebuilt page, v2
   Loaded only by contact.html. Scoped under .px-contact so it cannot leak.

   Modelled on a client-supplied reference (a biotech site's contact page):
   a big headline + social row on the left, "Contact Info" / "Address"
   columns and a plain underlined-field form on the right — nothing boxed,
   nothing carded, everything just sitting on the page. The one deliberate
   departure from the reference is the background: the client asked to KEEP
   the existing footage (ContactusSS.mp4) playing full-bleed behind all of
   it, in place of the reference's flat cream ground. Which means every
   piece of type here is light-on-video, not dark-on-cream — see the scrim
   and text-shadow notes below for how that is kept legible.

   `.px-hero` is ONE full-bleed layer (video + scrim), with a 2-column grid
   of content sitting on top of it — not a split-screen like the v1 design.
   Each column is its own flex column with `justify-content:space-between`,
   so the heavy content (headline; info + form) sits at the top and the
   lighter content (socials; submit button) anchors the bottom — that's what
   produces the same "pinned corners" composition the reference has, without
   needing a 3-row grid.

   ONE SCREEN, NO SCROLL on desktop — same client preference as v1. Below
   1025px a true 2-column layout has no room to work, so it drops to a single
   stacked column with the page scrolling normally (see the responsive
   section at the foot of this file).
   ========================================================================== */

.px-contact {
  --gutter: clamp(22px, 5vw, 96px);
  --px-head: 100px;          /* the overlaying header / the negative margin,
                                 see the sizing section at the foot for why */
  background: #000;
  color: var(--px-cream);

  /* break out of the theme's centred .qodef-content-grid so the hero plate
     runs edge to edge */
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.px-contact *,
.px-contact *::before,
.px-contact *::after { box-sizing: border-box; }

/* The theme paints three 2px vertical rules down the whole page
   (.qodef-content-line, left / centre / right) as a decorative grid. On a
   page whose background is footage they read as scratches on the plate, so
   they are switched off here. This stylesheet only loads on contact.html, so
   the other pages keep them. */
.qodef-content-lines-holder { display: none !important; }

/* ---------------------------------------------------------------- hero --- */

.px-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.px-hero__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.px-hero__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  animation: px-drift 26s ease-in-out infinite alternate;
}

@keyframes px-drift {
  from { transform: scale(1.04); }
  to   { transform: scale(1.14); }
}

@media (prefers-reduced-motion: reduce) {
  .px-hero__media video { animation: none; transform: scale(1.04); }
}

/* Every piece of type in the grid below sits directly on this footage, so —
   unlike v1, where only a navy mood-wash lived here and the real contrast
   work happened in a solid-black side panel — this scrim is load-bearing.
   Darkest at the edges (where the headline and the form both start), lighter
   toward the centre so the footage still reads as footage, not a black
   rectangle with a video rumour behind it. */
.px-hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,.50) 0%, rgba(0,0,0,.18) 22%,
                            rgba(0,0,0,.22) 78%, rgba(0,0,0,.58) 100%),
    linear-gradient(90deg, rgba(0,0,0,.34) 0%, rgba(0,0,0,.08) 30%,
                           rgba(0,0,0,.08) 70%, rgba(0,0,0,.34) 100%);
}

/* ---------------------------------------------------------------- grid --- */

.px-hero__grid {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 5vh, 56px);
  padding: calc(var(--px-head) + clamp(18px, 3vh, 44px))
           var(--gutter)
           clamp(28px, 4vh, 52px);
}

.px-hero__left,
.px-hero__right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(28px, 4vh, 48px);
}

/* -------------------------------------------------------------- left --- */

.px-headline {
  margin: 0;
  max-width: 90%;
  /* explicit, not inherited from .px-contact's `color` -- the theme sets its
     own default on bare h1/h2/h3 (near-black, for the light template) with
     enough specificity to beat inheritance, which is never overridden by
     "more specific wins" logic because inheritance isn't a competing rule at
     all -- any explicit declaration, however weak, wins over none. Same trap
     the "white -> cream" work elsewhere on this site exists to route around;
     every other element in this file sets colour explicitly for exactly
     this reason, and this one was the single omission. */
  color: var(--px-cream);
  font-family: "Bebas Neue", sans-serif;
  font-weight: 400;
  font-size: clamp(32px, min(4.4vw, 6.6vh), 68px);
  line-height: 1.08;
  letter-spacing: .01em;
  text-shadow: 0 2px 14px rgba(0, 0, 0, .55);
}

.px-socials {
  display: flex;
  gap: clamp(14px, 1.6vw, 22px);
}

.px-socials a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(38px, 2.6vw, 46px);
  height: clamp(38px, 2.6vw, 46px);
  border: 1px solid rgba(226, 224, 215, .4);
  border-radius: 50%;
  color: var(--px-cream);
  font-size: clamp(15px, 1.1vw, 18px);
  text-decoration: none;
  transition: border-color .25s ease, color .25s ease, background-color .25s ease;
}

.px-socials a:hover {
  color: var(--px-cream);
  border-color: var(--px-red);
  background: var(--px-red);
}

/* ------------------------------------------------------------- right --- */

/* Client asked for this block "much bigger" (Oct 2026) — it used to run at
   small functional-label sizes (13-16px), which made sense next to the form
   it sat beside, but the form is gone (see below) and this is now the only
   content in the right-hand column, so it reads as an afterthought at the
   old scale. Sized and spaced up accordingly; see the two blocks below. */
.px-info {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 5vw, 96px);
}

/* NOT BLOOD. This is a functional label and has to actually read:
   BLOOD's relative luminance (0.0816) caps its contrast at 2.63:1 against
   pure black, under the 3:1 floor for text this size — the same measurement
   the v1 brief form's label already ran into and fixed the same way (see
   that file's own "NOT BLOOD" comment in git history). BLOOD stays fine as
   a large accent (the office city names, the active-nav mark) but not here. */
.px-info__col h4 {
  font-family: "Bebas Neue", sans-serif;
  font-weight: 400;
  font-size: clamp(18px, 1.8vw, 24px);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--px-cream);
  margin: 0 0 clamp(14px, 1.8vh, 20px);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
}

.px-info__col p {
  margin: 0 0 .5em;
  color: var(--px-cream-soft);
  font-size: clamp(20px, 1.9vw, 28px);
  line-height: 1.45;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
}

.px-info__col p:last-child { margin-bottom: 0; }

.px-info__col a {
  color: var(--px-cream);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .25s ease, border-color .25s ease;
}

.px-info__col a:hover { color: var(--px-red); border-color: var(--px-red); }

/* The contact form (#px-contact-form, .px-field, .px-form-bottom,
   .px-form-status) and its .px-btn submit button were removed site-wide at
   the client's request (Oct 2026) — the Address column's own links are now
   the only interactive content on the right-hand column. Their CSS went with
   them; see pixels-contact.js for the matching, already-defensive JS (its
   submit handler already no-ops when #px-contact-form is absent). */

/* ------------------------------------------------------------- reveals --- */

.px-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .8s cubic-bezier(.2,.6,.2,1), transform .8s cubic-bezier(.2,.6,.2,1);
}

.px-reveal.px-in { opacity: 1; transform: none; }
/* the stagger lives in pixels-contact.js (by document order) */

@media (prefers-reduced-motion: reduce) {
  .px-reveal { opacity: 1; transform: none; transition: none; }
}

/* ------------------------------------------------- one-screen sizing --- */

/* Desktop only.
   NOTE: the theme's `#qodef-page-outer { margin-top:-100px }` does NOT shift
   this content — the 100px header sits in flow above it and the negative
   margin just cancels that out, so the hero's top lands at viewport 0.
   Measured, not assumed, in v1: adding the 100px back made the document
   exactly 100px taller than the window at every size. So the height here is
   a plain 100svh. --px-head is still needed for the top PADDING, because the
   header paints *over* the hero even though it does not displace it. */
@media only screen and (min-width: 1025px) {
  .px-contact { overflow: hidden; }

  .px-hero {
    height: 100svh;
    min-height: 640px;
  }

  .px-hero__grid {
    height: 100%;
    flex-direction: row;
    /* Client feedback (Oct 2026): the space-between layout below used to pin
       the headline/socials and info/form to the very top and bottom edges of
       the screen, which read as "stuck to the top" rather than composed. The
       columns are no longer stretched to fill the full height (that stretch
       is what space-between needed to push content apart in the first
       place) -- each column now sizes to its own content and the pair is
       centred as a block in the available space instead. */
    align-items: center;
  }

  .px-hero__left,
  .px-hero__right { flex: 1 1 50%; min-width: 0; }
}

/* --------------------------------------------------------------- small --- */

/* Below 1025px the 2-column grid has no room: the headline would fight the
   info/form column for width and both would wrap badly. Stack into one
   column instead and restore normal page scrolling.

   The video stays as the backdrop for the WHOLE stack, which is taller than
   one screen once everything is stacked — stretching an absolutely
   positioned, `object-fit:cover` video to match that height would crop it
   down to a narrow vertical sliver (cover grows to fill the taller box by
   cropping width, not by showing more of the frame). `position:fixed`
   instead pins it to the viewport itself, so it always covers exactly
   100vw x 100vh at its intended crop, and the stacked content simply
   scrolls over it — the same "persistent video backdrop" pattern as a
   fixed hero, just applied to the whole page instead of one screen. */
@media (max-width: 1024px) {
  .px-hero__media,
  .px-hero__scrim { position: fixed; }

  .px-hero__grid { flex-direction: column; }
  .px-hero__left,
  .px-hero__right { gap: clamp(22px, 4vh, 36px); }
  .px-headline { max-width: 16ch; }
}

@media (max-width: 640px) {
  .px-info { gap: 28px; }
  .px-socials a { width: 40px; height: 40px; }
}
