/* ===========================================================================
   Nirvana Carbon Solutions - Page 1, the gate.
   One screen. A living impressionist painting behind a small amount of
   approved text and one button. Nothing below the fold, no nav, no login.

   The immersion recipe:
     - three feathered layers of the painting, pointer-parallaxed at
       different depths (gate.js, rAF-lerped, transform-only)
     - a very slow breathing drift on the whole stack (CSS, compositor)
     - a bone radial haze that holds the type at AA over the brushwork
   All motion honours prefers-reduced-motion and touch devices fall back to
   drift-only. If gate.js never runs the page is a static painting with
   readable text and a working mailto link.
   =========================================================================== */

@font-face {
  font-family: "Fraunces";
  src: url("fonts/Fraunces-latin.woff2") format("woff2");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("fonts/IBMPlexSans-var.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --forest-900: #0F1A13;
  --forest-800: #16241A;
  --forest-700: #1F4429;
  --forest-600: #2E6B32;
  --paper:      #F6F5EE;
  --bone:       #EFEDE2;
  --gold:       #C9A227;
  --ink-soft:   rgba(22, 36, 26, .78);

  --serif: "Fraunces", ui-serif, Georgia, "Times New Roman", serif;
  --sans:  "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Motion-sampled spring (generate-css-easing), banked earlier. */
  --spring: linear(0, 0.0671, 0.215, 0.3869, 0.5505, 0.69, 0.8, 0.8814, 0.9381,
                   0.975, 0.9972, 1.0091, 1.0142, 1.0151, 1.0138, 1.0114, 1.0088,
                   1.0064, 1.0043, 1.0028, 1.0016, 1.0008, 1.0003, 1, 1);
  --spring-dur: 750ms;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }
/* All three properties, deliberately. Only the -webkit- form was set, which
   Blink honours and Gecko ignores, so Firefox for Android applied its own text
   inflation and rendered the page about 18% larger than Chrome on the same
   phone. This is what made the two browsers disagree. */
html {
  -webkit-text-size-adjust: 100%;
  -moz-text-size-adjust: 100%;
  text-size-adjust: 100%;
  height: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--paper);
  color: var(--forest-800);
  font-family: var(--sans);
  font-size: clamp(1rem, .96rem + .2vw, 1.0625rem);
  line-height: 1.6;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img { display: block; max-width: 100%; height: auto; }

/* ---------------- The painting: three parallax layers -------------------- */
.scene {
  position: fixed; inset: 0;
  overflow: hidden;
  background: #E9E2CE; /* painting's field tone while layers load */
  z-index: 0;
}
/* Each layer is overscanned so parallax never shows an edge. gate.js moves
   .scene__move wrappers; the drift lives on .scene__drift so the two
   transforms never fight for the same element. */
.scene__drift { position: absolute; inset: 0; }
.scene__move  { position: absolute; inset: -3.2%; }
@media (hover: hover) and (pointer: fine) {
  .scene__move { will-change: transform; }
}
.scene__move img, .scene__move picture { position: absolute; inset: 0; width: 100%; height: 100%; }
.scene__move img { object-fit: cover; object-position: 58% 78%; }

@media (prefers-reduced-motion: no-preference) {
  .scene__drift {
    animation: breathe 46s var(--ease) infinite alternate;
    transform-origin: 55% 70%;
  }
  @keyframes breathe {
    from { transform: scale(1); }
    to   { transform: scale(1.055); }
  }
}

/* Bone haze: a radial pool of light behind the content column, so ink type
   holds 4.5:1 over the brushwork. Measured on rendered pixels, not assumed. */
.scene__haze {
  position: absolute; inset: -4%;
  background:
    radial-gradient(ellipse 54% 70% at 50% 44%,
      rgba(243, 240, 228, .84) 0%,
      rgba(243, 240, 228, .68) 40%,
      rgba(243, 240, 228, .34) 66%,
      rgba(243, 240, 228, .06) 86%,
      rgba(243, 240, 228, 0) 100%),
    linear-gradient(to top, rgba(243, 240, 228, .38) 0%, rgba(243, 240, 228, 0) 22%);
  pointer-events: none;
}
/* Mobile shows a narrow slice of the painting, so the haze eases to let the
   village read through; contrast re-measured after (13:1 headroom existed).
   The mid/fore layers exist only for pointer parallax, which never arms on
   touch, so phones neither download nor composite them. */
@media (max-width: 40rem) {
  .scene__move:nth-child(2), .scene__move:nth-child(3) { display: none; }
  .scene__haze {
    background:
      radial-gradient(ellipse 78% 62% at 50% 36%,
        rgba(243, 240, 228, .78) 0%,
        rgba(243, 240, 228, .58) 44%,
        rgba(243, 240, 228, .22) 70%,
        rgba(243, 240, 228, 0) 100%),
      linear-gradient(to top, rgba(243, 240, 228, .30) 0%, rgba(243, 240, 228, 0) 20%);
  }
  .scene__move img { object-position: 62% 62%; }
}

/* ---------------- The one screen of content ------------------------------ */
.gate {
  position: relative; z-index: 1;
  min-height: 100vh; min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
}
.gate__inner {
  align-self: center;
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  width: min(100% - 3rem, 62rem);
  padding-block: clamp(2.5rem, 6vh, 5rem) clamp(1.5rem, 3vh, 2.5rem);
}

.gate__mark { width: clamp(58px, 8vh, 84px); height: auto; }
.gate__word {
  margin-top: 1rem;
  font-family: var(--sans);
  font-size: clamp(.78rem, .7rem + .3vw, .95rem);
  font-weight: 600;
  letter-spacing: .34em; text-indent: .34em; /* balance the tracking */
  text-transform: uppercase;
  color: var(--forest-700);
}

.gate h1 {
  margin: clamp(1.4rem, 3.5vh, 2.4rem) 0 0;
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.7rem, 1rem + 2.9vw, 3.3rem);
  line-height: 1.12;
  letter-spacing: -.022em;
  font-variation-settings: "SOFT" 18, "WONK" 1, "opsz" 96;
  max-width: 21ch;
  text-wrap: balance;
}

.gate__mv {
  margin-top: clamp(1.8rem, 4.5vh, 3.2rem);
  display: grid; gap: clamp(1rem, 2.4vw, 2rem);
  max-width: 56rem;
}
@media (min-width: 46rem) { .gate__mv { grid-template-columns: 1fr 1fr; } }
/* Each section is a pane of liquid glass over the painting: a light gradient
   fill, a deep blur that smooths the brushwork into legibility, a specular
   top edge and a soft rim. The scene itself is untouched - the pop lives
   entirely on the panels. Text contrast only gains here: the glass adds
   light over a haze the type already passed AA on bare. */
.gate__mv section {
  padding: clamp(1rem, 2.2vw, 1.35rem) clamp(1.1rem, 2.6vw, 1.5rem) clamp(1.15rem, 2.4vw, 1.45rem);
  background:
    linear-gradient(155deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, .05) 40%, rgba(255, 255, 255, 0) 65%),
    linear-gradient(rgba(246, 245, 238, .46), rgba(246, 245, 238, .32));
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: 16px;
  -webkit-backdrop-filter: blur(18px) saturate(1.35);
  backdrop-filter: blur(18px) saturate(1.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .55),
    inset 0 -1px 0 rgba(22, 36, 26, .05),
    0 10px 30px rgba(15, 26, 19, .10);
  transition: transform 260ms var(--ease), box-shadow 260ms var(--ease),
              border-color 260ms var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .gate__mv section:hover {
    transform: translateY(-5px);
    border-color: rgba(201, 162, 39, .55);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .65),
      inset 0 -1px 0 rgba(22, 36, 26, .05),
      0 20px 46px rgba(15, 26, 19, .16);
  }
  .gate__mv section:hover h2::after { transform: scaleX(1.6); }
}
.gate__mv h2 {
  margin: 0 0 .45rem;
  font-family: var(--sans);
  font-size: .74rem; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--forest-600);
}
.gate__mv h2::after {
  content: ""; display: block; width: 2.2rem; height: 2px;
  background: var(--gold); margin: .55rem auto 0;
  transform-origin: center;
  transition: transform 260ms var(--ease);
}
.gate__mv p {
  margin: 0;
  font-size: clamp(.92rem, .88rem + .2vw, 1.02rem);
  line-height: 1.55;
  color: rgba(22, 36, 26, .85); /* a notch darker than --ink-soft: glass duty */
  max-width: 40ch;
  margin-inline: auto;
}

/* CTA: three nested transform owners (see index.html). The wrap carries the
   entrance, the mag carries the JS magnetic pull, the anchor carries the idle
   float. The ground shadow sits on the mag so the button floats over it. */
.gate__ctaWrap { margin-top: clamp(1.9rem, 5vh, 3.2rem); }
.gate__ctaRow {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: .9rem;
}
.gate__ctaSlot { position: relative; }
.gate__ctaMag  { position: relative; }
/* The Foundation: a quiet liquid-glass ghost beside the primary. */
.gate__cta {
  display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
  min-height: 52px; padding: .8rem 2rem;
  font: 600 1rem var(--sans); letter-spacing: -.005em;
  text-decoration: none;
  color: var(--paper); background: var(--forest-800);
  border: 1px solid var(--forest-800); border-radius: 999px;
  cursor: pointer;
  transition: background-color 200ms var(--ease), box-shadow 260ms var(--ease);
}
.gate__cta:hover {
  background: var(--forest-700);
  box-shadow: 0 0 0 5px rgba(201, 162, 39, .32), 0 16px 34px rgba(15, 26, 19, .22);
}
.gate__cta:active { background: var(--forest-900); }
@media (prefers-reduced-motion: no-preference) {
  .gate__cta { animation: ctaFloat 4.6s ease-in-out infinite alternate; }
  @keyframes ctaFloat {
    from { transform: translateY(0); }
    to   { transform: translateY(-5px); }
  }
  .gate__ctaMag::after {
    content: ""; position: absolute; z-index: -1;
    left: 16%; right: 16%; bottom: -11px; height: 10px;
    border-radius: 50%;
    background: radial-gradient(ellipse at center, rgba(15, 26, 19, .30), rgba(15, 26, 19, 0) 70%);
    animation: ctaShadow 4.6s ease-in-out infinite alternate;
  }
  @keyframes ctaShadow {
    from { transform: scaleX(1);   opacity: .55; }
    to   { transform: scaleX(.84); opacity: .32; }
  }
}
@media (hover: hover) and (pointer: fine) {
  .gate__ctaMag { will-change: transform; }
}

.gate__foot {
  /* The UA's default 1em paragraph margin has nothing to collapse against
     inside the bare <footer>, so it collapsed straight out of the grid row and
     carried the footer ~10px past 100svh - which is what put this page below
     the fold on a phone. Zero it; the padding above owns the spacing. */
  margin: 0;
  padding: 0 1.5rem clamp(1rem, 2.5vh, 1.6rem);
  font-size: .78rem;
  color: var(--ink-soft);
}

:where(a, button):focus-visible {
  outline: 2px solid var(--forest-600);
  outline-offset: 3px;
}

/* ---------------- Contact: the reveal card ------------------------------- */
dialog:not([open]) { display: none; }
.card { /* <dialog> */
  border: 1px solid rgba(22, 36, 26, .18);
  border-radius: 12px;
  padding: clamp(1.5rem, 4vw, 2.2rem);
  width: min(92vw, 29rem);
  max-height: min(88dvh, 46rem);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(22, 36, 26, .30) transparent;
  background: var(--paper);
  color: var(--forest-800);
  box-shadow: 0 24px 70px rgba(15, 26, 19, .28);
}
/* The painting melts out of focus behind the card - the quiet immersive cue.
   The rgba dim beneath is the no-backdrop-filter fallback. */
.card::backdrop {
  background: rgba(15, 26, 19, .38);
  -webkit-backdrop-filter: blur(7px) saturate(1.08);
  backdrop-filter: blur(7px) saturate(1.08);
}
@media (prefers-reduced-motion: no-preference) {
  .card[open] { animation: cardIn var(--spring-dur) var(--spring); }
  @keyframes cardIn {
    from { opacity: 0; transform: translateY(18px) scale(.97); }
    to   { opacity: 1; transform: none; }
  }
  .card[open]::backdrop { animation: backdropIn 340ms var(--ease); }
  @keyframes backdropIn { from { opacity: 0; } to { opacity: 1; } }
  /* Fields arrive in reading order, just behind the card itself. */
  .card[open] .card__field, .card[open] .card__send,
  .card[open] .card__alt,   .card[open] .card__mail {
    animation: fieldIn 460ms var(--spring) both;
  }
  .card[open] .card__field:nth-of-type(1) { animation-delay: 70ms; }
  .card[open] .card__field:nth-of-type(2) { animation-delay: 120ms; }
  .card[open] .card__field:nth-of-type(3) { animation-delay: 170ms; }
  .card[open] .card__field:nth-of-type(4) { animation-delay: 220ms; }
  .card[open] .card__send { animation-delay: 280ms; }
  .card[open] .card__alt  { animation-delay: 330ms; }
  .card[open] .card__mail { animation-delay: 360ms; }
  @keyframes fieldIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
  }
}
.card h2 {
  margin: 0 0 .4rem;
  font-family: var(--serif); font-weight: 500;
  font-size: 1.45rem; letter-spacing: -.015em;
}
.card__sub { margin: 0 0 1.2rem; font-size: .95rem; color: var(--ink-soft); }

/* The form, shaped after a labelled get-in-touch form: label over field,
   soft rounded inputs, one primary send. Sending composes the visitor's own
   email; nothing is collected by the page. */
.card__form { display: grid; gap: .85rem; text-align: left; }
.card__field { display: grid; gap: .3rem; }
.card__field label {
  font: 600 .72rem var(--sans);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--forest-700);
}
.card__field label span {
  text-transform: none; letter-spacing: 0;
  font-weight: 400; color: var(--ink-soft);
}
.card__field input, .card__field textarea {
  width: 100%; padding: .68rem .8rem;
  font: 400 .95rem var(--sans); line-height: 1.45;
  color: var(--forest-800); background: #FFFFFF;
  border: 1px solid rgba(22, 36, 26, .28); border-radius: 8px;
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}
.card__field input::placeholder, .card__field textarea::placeholder {
  color: rgba(22, 36, 26, .45);
}
.card__field input:focus, .card__field textarea:focus {
  outline: none;
  border-color: var(--forest-600);
  box-shadow: 0 0 0 3px rgba(46, 107, 50, .18);
}
.card__field textarea { resize: vertical; min-height: 96px; }
.card__send {
  margin-top: .2rem;
  min-height: 48px; width: 100%;
  font: 600 .95rem var(--sans);
  color: var(--paper); background: var(--forest-800);
  border: 0; border-radius: 999px; cursor: pointer;
  transition: background-color 180ms var(--ease);
}
.card__send:hover { background: var(--forest-700); }
.card__alt {
  margin: 1rem 0 .5rem; text-align: center;
  font-size: .82rem; color: var(--ink-soft);
}
.card__mail {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem;
  border: 1px solid rgba(22, 36, 26, .2); border-radius: 8px;
  padding: .85rem 1rem;
}
.card__mail a {
  display: inline-block; padding-block: .55rem;
  font-weight: 600; font-size: .98rem; color: var(--forest-800);
  text-decoration: none; border-bottom: 1px solid rgba(22, 36, 26, .25);
  overflow-wrap: anywhere;
}
.card__mail a:hover { border-bottom-color: currentColor; }
.card__copy {
  flex: none;
  min-height: 44px; padding: .5rem .95rem;
  font: 600 .85rem var(--sans);
  color: var(--forest-800); background: transparent;
  border: 1px solid rgba(22, 36, 26, .35); border-radius: 999px;
  cursor: pointer;
  transition: background-color 180ms var(--ease);
}
.card__copy:hover { background: rgba(22, 36, 26, .06); }
.card__status { min-height: 1.2em; margin-top: .6rem; font-size: .85rem; font-weight: 600; color: var(--forest-600); }
.card__close { /* secondary next to the primary send */
  margin-top: 1rem;
  min-height: 44px; width: 100%;
  font: 600 .95rem var(--sans);
  color: var(--forest-800); background: transparent;
  border: 1px solid rgba(22, 36, 26, .35); border-radius: 999px; cursor: pointer;
  transition: background-color 180ms var(--ease);
}
.card__close:hover { background: rgba(22, 36, 26, .06); }

/* ---------------- Entrance ------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  .gate__mark, .gate__word, .gate h1, .gate__mv, .gate__ctaWrap, .gate__foot {
    animation: arrive var(--spring-dur) var(--spring) both;
  }
  .gate__word    { animation-delay: 90ms; }
  .gate h1       { animation-delay: 180ms; }
  .gate__mv      { animation-delay: 290ms; }
  .gate__ctaWrap { animation-delay: 400ms; }
  .gate__foot    { animation-delay: 480ms; }
  @keyframes arrive {
    from { opacity: 0; transform: translate3d(0, 22px, 0); }
    to   { opacity: 1; transform: none; }
  }
}

/* One screen is a hard requirement here, not a preference: BUILD-BRIEF §1 asks
   for "genuinely nothing below the fold". The rhythm below is built from rem
   floors, and on a phone those floors are what overflowed - 43px past the fold
   at 375x812, 195px at 360x640. So on phone widths the whole vertical rhythm
   compresses with the viewport instead of pushing the footer off the screen. */
@media (max-width: 46rem) {
  .gate__inner { padding-block: clamp(1.2rem, 3.4vh, 2.6rem) clamp(.7rem, 1.6vh, 1.2rem); }
  .gate__mark { width: clamp(40px, 5.4vh, 62px); }
  .gate__word { margin-top: .55rem; }
  .gate h1 { margin-top: clamp(.8rem, 2.2vh, 1.7rem); }
  .gate__mv { margin-top: clamp(.9rem, 2.4vh, 2.1rem); gap: clamp(.6rem, 1.5vh, 1.15rem); }
  .gate__mv section { padding: clamp(.7rem, 1.6vh, 1.2rem) clamp(1.1rem, 2.6vw, 1.5rem); }
  .gate__mv p { line-height: 1.46; }
  .gate__ctaWrap { margin-top: clamp(.9rem, 2.4vh, 2.2rem); }
  .gate__ctaRow { gap: .6rem; }
  .gate__foot { padding-bottom: clamp(.6rem, 1.4vh, 1.2rem); }
}

/* Short-viewport safety: below this the copy itself has to give, not just the
   spacing. Anything shorter may scroll, but there is nothing extra to reach. */
@media (max-height: 700px) {
  .gate__inner { padding-block: 1.15rem .75rem; }
  .gate h1 { font-size: clamp(1.4rem, 3.6vh, 2rem); }
  .gate__cta { min-height: 46px; padding: .65rem 1.6rem; }
}

@media (prefers-reduced-transparency: reduce) {
  .gate__mv section {
    /* solid, but with the same sheen so it never reads as a flat white box */
    background: linear-gradient(155deg, #F6F4EA, #EFEDE2 60%);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .card::backdrop { -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  :root { --ink-soft: #16241A; }
  .scene__haze {
    background:
      radial-gradient(ellipse 66% 82% at 50% 44%,
        rgba(243, 240, 228, .99) 0%, rgba(243, 240, 228, .95) 55%,
        rgba(243, 240, 228, .55) 82%, rgba(243, 240, 228, .2) 100%);
  }
  .gate__mv section {
    background: var(--paper);
    border-color: var(--forest-800);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}
@media print {
  .scene, dialog { display: none; }
  body { background: #fff; }
  .gate__mark, .gate__word, .gate h1, .gate__mv, .gate__ctaWrap, .gate__cta, .gate__foot {
    animation: none !important; opacity: 1 !important; transform: none !important;
  }
  .gate__mv section { box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
