/* ky-reveal — Curtain Call styles.
   Every motion state here is keyed off ROOT classes that ky-reveal.js
   stamps (html.ky-cc-live / .ky-cc-words-in / .ky-cc-card-in), so a React
   rebuild of the body never wipes reveal state, and a browser without the
   driver (mobile, reduced motion, JS off) renders the settled page: the
   band pin falls back to -100px, the word pin never applies, and ky-flow's
   own 22px card reveal keeps working untouched. */


/* ---- the three per-frame channels, typed ---------------------------------
   ky-reveal.js writes these once a frame for the length of the scrub. Left
   unregistered they are parsed as raw token streams on every write and every
   read; registered, the engine stores a length and a number and skips the
   reparse. The initial values are exactly the fallbacks the var() call sites
   already carry, so an unset property renders identically to before —
   registration changes the cost, not the picture.

   inherits: true is REQUIRED, not incidental. The driver normally writes to
   the band element, but falls back to <html> when the band is missing or no
   longer contains #Contact; on that path --kyrv-sh and --kyrv-lag have to
   reach a child and a descendant respectively, and --kyrv-y has to reach the
   band from the root. A non-inheriting registration would silently break the
   fallback and strand the band off-screen. */
@property --kyrv-y {
  syntax: "<length>";
  inherits: true;
  initial-value: -100px;
}
@property --kyrv-sh {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --kyrv-lag {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

/* ---- occlusion shadow: the page above casts onto the emerging band ------- */
html.ky-cc-live div.section-padding-x[class*="translate-y-[-20vh]"] > div.relative::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 110px;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(5, 5, 4, 0.62), rgba(5, 5, 4, 0));
  opacity: var(--kyrv-sh, 0);
  pointer-events: none;
  z-index: 3;
}

/* ---- the giant "LET'S MAKE IT HAPPEN" word spans -------------------------
   The site engine reveals these whileInView against the RENDERED rect; the
   tuck makes that fire early and invisibly behind #About. Pin = visibility
   (a channel no engine writes, so no !important war), release = a CSS
   animation, which outranks the engine's inline opacity/transform for its
   whole run and holds the final frame via fill:both. The 10s bail un-hides
   everything if the driver dies while the pin stands; a later replay from
   the bail state still starts at the hidden first keyframe, so it reads as
   the intended rise, not a glitch. */
html.ky-cc-live:not(.ky-cc-words-in)
  div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block {
  visibility: hidden;
  animation: ky-ccw-bail 1ms step-end 10s forwards;
}
@keyframes ky-ccw-bail {
  to { visibility: visible; }
}

html.ky-cc-live.ky-cc-words-in
  div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block {
  animation: ky-ccw-rise 0.58s cubic-bezier(.51, .92, .24, 1.15) both;
}
@keyframes ky-ccw-rise {
  from { opacity: 0; transform: translateY(112%); visibility: visible; }
  to   { opacity: 1; transform: translateY(0%);   visibility: visible; }
}
/* The engine's split leaves EMPTY spans at 2,3,5,7,9; the visible words sit
   at 1 "Let's", 4 "Make", 6 "It", 8 "Happen" — delays target those so the
   felt cadence is ~85ms/word, not the raw sibling index. */
html.ky-cc-live.ky-cc-words-in
  div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block:nth-child(4) { animation-delay: 0.09s; }
html.ky-cc-live.ky-cc-words-in
  div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block:nth-child(6) { animation-delay: 0.17s; }
html.ky-cc-live.ky-cc-words-in
  div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block:nth-child(8) { animation-delay: 0.24s; }

/* ---- the contact card: pulled from behind the page ------------------------
   Under the live flag this pair OWNS the card's entrance; ky-flow's generic
   .ky-rv / .ky-rv-in still toggles classes from its own IO (which fires
   invisibly against the tucked rect) but the ID selector here outranks its
   visuals, so WHAT the visitor sees is timed purely by ky-cc-card-in. */
/* The drawer descends, so its contents must descend too. The old entrance
   came UP from +64px, against the band's direction, which is a large part of
   why the moment read as a modal fading in rather than a drawer being pulled
   out — two opposing motions cancelling each other's story.

   scale(0.96) is gone with it. On a card this size a scale is the one
   transform that cannot be composited cheaply here: it forces the blurred
   backdrop underneath to re-rasterise at a new size every frame, and it reads
   as "dialog pops" rather than "drawer slides".

   `translate` carries the per-frame trailing lag from ky-reveal.js and is
   deliberately left out of the transition list below — it must track the
   driver exactly, while `transform` and `opacity` tween on their own clock.
   Two channels on one element, neither fighting the other. */
html.ky-cc-live #Contact {
  opacity: 0;
  transform: translateY(-22px);
  translate: 0 var(--kyrv-lag, 0px);
}
html.ky-cc-live.ky-cc-card-in #Contact {
  opacity: 1;
  transform: none;
  /* no overshoot on the container: the lag already supplies the settle, and
     an overshooting card on top of a lagging card double-bounces */
  transition:
    opacity 0.5s cubic-bezier(.22, .61, .36, 1),
    transform 0.56s cubic-bezier(.22, .61, .36, 1);
}

/* children cascade — pure CSS tiers, zero writes inside React's form */
html.ky-cc-live #Contact .ky-cc-kick,
html.ky-cc-live #Contact form > div,
html.ky-cc-live #Contact form > button {
  opacity: 0;
  transform: translateY(-16px);   /* with the drawer, not against it */
}
html.ky-cc-live #Contact .ky-cc-mwi {
  transform: translateY(112%);
}
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-kick,
html.ky-cc-live.ky-cc-card-in #Contact form > div,
html.ky-cc-live.ky-cc-card-in #Contact form > button {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.4s cubic-bezier(.22, .61, .36, 1),
    transform 0.44s cubic-bezier(.51, .92, .24, 1.15);
}
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mwi {
  transform: none;
  transition: transform 0.5s cubic-bezier(.51, .92, .24, 1.15);
}
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-kick            { transition-delay: 0.04s; }
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mw:nth-child(1) .ky-cc-mwi { transition-delay: 0.08s; }
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mw:nth-child(2) .ky-cc-mwi { transition-delay: 0.13s; }
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mw:nth-child(3) .ky-cc-mwi { transition-delay: 0.18s; }
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mw:nth-child(4) .ky-cc-mwi { transition-delay: 0.23s; }
html.ky-cc-live.ky-cc-card-in #Contact .ky-cc-mw:nth-child(5) .ky-cc-mwi { transition-delay: 0.28s; }
/* Tail compressed 0.41s -> 0.29s. The cascade now STARTS while the band is
   still settling, so the old tail would have run well past the drawer coming
   to rest and split the moment in two again at the other end. */
html.ky-cc-live.ky-cc-card-in #Contact form > div:nth-of-type(1)  { transition-delay: 0.17s; }
html.ky-cc-live.ky-cc-card-in #Contact form > div:nth-of-type(2)  { transition-delay: 0.23s; }
html.ky-cc-live.ky-cc-card-in #Contact form > div:nth-of-type(3)  { transition-delay: 0.29s; }
html.ky-cc-live.ky-cc-card-in #Contact form > button              { transition-delay: 0.34s; }

/* ---- card h2 word masks (always harmless; only move under the flags) ----- */
#Contact h2 .ky-cc-mw {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}
#Contact h2 .ky-cc-mwi {
  display: inline-block;
}

/* ---- coded kicker — the house Montreal-Mono label vocabulary -------------- */
#Contact .ky-cc-kick {
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--color-accent-200, #E3AC33) 62%, transparent);
  margin-bottom: 14px;
  user-select: none;
}
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  #Contact .ky-cc-kick { color: var(--color-accent-200, #E3AC33); opacity: 0.62; }
}

/* ---- form micro-interactions (ungated: mobile deserves focus polish) ------ */
#Contact form input[type="text"],
#Contact form input[type="email"],
#Contact form textarea {
  caret-color: var(--color-accent-200, #E3AC33);
  background-image: linear-gradient(
    90deg,
    var(--color-accent-200, #E3AC33),
    color-mix(in srgb, var(--color-accent-200, #E3AC33) 35%, transparent)
  );
  background-repeat: no-repeat;
  background-position: left calc(100% - 1px);
  background-size: 0% 2px;
  transition:
    background-size 0.24s cubic-bezier(.51, .92, .24, 1.15),
    border-color 0.18s ease,
    box-shadow 0.18s ease,
    background-color 0.18s ease;
}
#Contact form input[type="text"]:focus,
#Contact form input[type="email"]:focus,
#Contact form textarea:focus {
  outline: none;
  background-size: 100% 2px;
  background-color: rgba(255, 255, 255, 0.07);
  border-color: color-mix(in srgb, var(--color-accent-200, #E3AC33) 45%, transparent);
  /* hairline ring, not a glow — restrained luxe wants a line */
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--color-accent-200, #E3AC33) 30%, transparent);
}
#Contact form ::placeholder {
  transition: color 0.2s ease;
}

/* DARK-GROUND INK FOR THE FORM — the fields were unreadable.
   ---------------------------------------------------------------------------
   The contact card is the one DARK surface on this page: rgba(209,209,199,.05)
   over the near-black band, compositing to about rgb(42,41,38). The fields
   were inheriting the honey theme's LIGHT-ground ink anyway:

     typed text   --color-foreground      -> rgb(20,17,10)   MEASURED 1.30:1
     placeholder  --color-secondary-100   -> rgb(83,65,26)   MEASURED 1.48:1
                  (= color-mix(in srgb, #2A2313 78%, #E3AC33))

   1.30:1 is not "low contrast", it is invisible — you could type a whole
   message into this form and never see a character of it. Both tokens are
   correct on the amber hero and wrong the moment the surface goes dark; the
   document's own inline sheet pins the placeholder one with !important, which
   is why nothing downstream had managed to correct it.

   Re-solved against the composited card, not against the token's intended
   ground: text 12.4:1, placeholder 4.81:1 (AA at any size). The focus state
   keeps its deliberate recede but lands at 2.75:1 instead of the 1.9:1 the
   old rgba(255,255,255,.22) gave — dimmed, not erased.

   Scoped to #Contact form's fields only, so the amber submit button keeps its
   dark-on-light ink. !important + the #id are what it takes to outrank the
   inline `input::placeholder{color:var(--color-secondary-100) !important}`. */
#Contact form :is(input, textarea) {
  color: #F2ECE0 !important;
  caret-color: var(--color-accent-200, #E3AC33);
}
#Contact form :is(input, textarea)::placeholder {
  color: rgba(242, 236, 224, 0.55) !important;
}
#Contact form :is(input, textarea):focus::placeholder {
  color: rgba(242, 236, 224, 0.34) !important;
}

/* button: typographic breath on hover instead of a gloss sweep */
#Contact form button[type="submit"] {
  letter-spacing: 0.02em;
  transition:
    letter-spacing 0.26s cubic-bezier(.51, .92, .24, 1.15),
    background-color 0.12s ease,
    transform 0.1s ease,
    box-shadow 0.2s ease;
}
#Contact form button[type="submit"]:hover {
  letter-spacing: 0.09em;
}
#Contact form button[type="submit"]:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--color-accent-200, #E3AC33) 70%, white);
  outline-offset: 2px;
}

/* ---- reduced motion: everything lands instantly, nothing hides ------------ */
@media (prefers-reduced-motion: reduce) {
  /* settle the band itself, ahead of the driver noticing the flip — this
     outranks the ky-contactfix pin (higher specificity, later sheet) */
  html.ky-cc-live div.section-padding-x[class*="translate-y-[-20vh]"] {
    transform: translateY(-100px) !important;
  }
  html.ky-cc-live div.section-padding-x[class*="translate-y-[-20vh]"] > div.relative::before {
    content: none;
  }
  html.ky-cc-live div.section-padding-x[class*="translate-y-[-20vh]"] h2 span.inline-block {
    visibility: visible !important;
    animation: none !important;
  }
  html.ky-cc-live #Contact,
  html.ky-cc-live #Contact .ky-cc-kick,
  html.ky-cc-live #Contact form > div,
  html.ky-cc-live #Contact form > button,
  html.ky-cc-live #Contact .ky-cc-mwi {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;   /* the lag channel, in case it was written */
    transition: none !important;
  }
  #Contact form input[type="text"],
  #Contact form input[type="email"],
  #Contact form textarea,
  #Contact form button[type="submit"] {
    transition: none;
  }
}
