/* drupe. — Steele & Hyland waitlist
   Static build of "Drupe Waitlist.dc.html" from the Claude Design project
   "Drupe Steele & Hyland Waitlist". Values track the design canvas; the DC
   runtime (x-dc / sc-if / {{ }} bindings / <image-slot>) is replaced by plain
   HTML, CSS and script.js.

   Tokens come from _ds/drupe-design-system-.../ — don't redefine them here. */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

/* The design system self-hosts "Mona Sans"; the CDN stand-in registers it as
   "Mona Sans Variable". Listing both means the self-hosted face wins the moment
   _ds/.../fonts/ is populated, with no further edit. */
:root {
  --font-sans: "Mona Sans", "Mona Sans Variable", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

/* Pure dissolve — no slide — for the hero's staggered entrance: the wordmark
   fades in first, then the release line, then the waitlist card, via the
   animation-delay each uses below. */
@keyframes heroDissolve {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- Page ground ---- */

.page {
  position: relative;
  width: 100%;
  min-height: 100dvh;
  overflow: hidden;
  background: #EEF4F2;
  font-family: var(--font-sans);
}

/* Base mood, and the fallback ground when the hero photo is absent. Layered
   to read as light through iced glass: soft top-down glow, a couple of
   condensation-bead highlights, warm pooling from the brand hues low in
   each corner, cool falloff at the base. */
.page__atmosphere {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(3% 2% at 27% 58%, rgba(255,255,255,.8), rgba(255,255,255,0) 100%),
    radial-gradient(2% 1.5% at 64% 71%, rgba(255,255,255,.7), rgba(255,255,255,0) 100%),
    radial-gradient(4% 3% at 71% 33%, rgba(255,255,255,.6), rgba(255,255,255,0) 100%),
    radial-gradient(120% 70% at 50% 6%, rgba(255,255,255,.6), rgba(255,255,255,0) 60%),
    radial-gradient(120% 90% at 12% 105%, rgba(74,35,40,.10), rgba(74,35,40,0) 55%),
    radial-gradient(120% 90% at 88% 105%, rgba(36,64,44,.09), rgba(36,64,44,0) 55%),
    linear-gradient(180deg, #F4F9F7 0%, #EEF4F2 48%, #E6EEE9 100%);
}

/* Macro still — iced glass, condensation, brine. A missing file simply doesn't
   paint, leaving .page__atmosphere as the ground. The source is a portrait
   photo; `cover` on a wide viewport blows it up into a tight, legible crop
   that reads as "zoomed-in photo" rather than ambient texture, so it's
   blurred into a soft frosted ground instead — scaled up first so the blur
   doesn't pull in a lighter halo at the (clipped) edges. */
.page__photo {
  position: absolute;
  inset: 0;
  background-image: url("assets/hero-ice.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(28px) saturate(105%);
  transform: scale(1.12);
}

/* A soft olive glow drifting behind the frosted photo — never sharpens, just
   travels. The blob lives in `background-position` (panned across an
   oversized `background-size`), not `transform`, so the keyframe percentages
   map onto the actual viewport-sized box and the glow crosses the full
   screen corner-to-corner rather than sliding a few percent of itself. */
@keyframes blobDrift {
  0%   { background-position: 0% 30%; }
  25%  { background-position: 100% 5%; }
  50%  { background-position: 90% 95%; }
  75%  { background-position: 5% 85%; }
  100% { background-position: 0% 30%; }
}

.page__blob {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(28% 24% at 50% 50%, rgba(36,64,44,.85), rgba(36,64,44,0) 70%);
  background-repeat: no-repeat;
  background-size: 180% 180%;
  filter: blur(50px);
  /* soft-light read as too faint against the photo's own moss-toned patch —
     multiply reliably darkens/greens wherever it travels, so the animated
     blob stays the dominant green feature instead of the static one in the
     photo pixels. */
  mix-blend-mode: multiply;
  animation: blobDrift 140s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .page__blob { animation: none; }
}

.page__grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

.page__veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(248,252,250,.55) 0%,
    rgba(248,252,250,0) 22%,
    rgba(248,252,250,0) 66%,
    rgba(244,249,247,.62) 100%);
}

/* ---- Frame ---- */

.page__frame {
  position: relative;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(20px, 4vw, 30px);
  padding-block: clamp(20px, 3.2vh, 30px);
  pointer-events: none;
}

.site-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
}

.wordmark {
  font-family: var(--font-serif-display);
  font-weight: var(--weight-serif-bold);
  font-size: 18px;
  line-height: 1;
  letter-spacing: var(--tracking-title);
  color: var(--oxblood);
}

/* ---- Hero ---- */

.hero {
  display: grid;
  justify-items: center;
  align-content: center;
  text-align: center;
  padding: clamp(8px, 2vh, 28px) 0;
}

/* Explicit durations/delays here rather than the shared --dur-reveal token
   (640ms, used elsewhere in the design system) — deliberately slow: three
   1400ms dissolves, each starting 500ms after the last, symmetric
   ease-in-out (not the design system's ease-out) so each fade eases in as
   gently as it eases out. Not tied to any fixed total — the pacing is
   chosen for feel, not a target duration. */
.hero__mark {
  margin: 0;
  animation: heroDissolve 1400ms ease-in-out both;
}

/* The delivered file is a 900×900 canvas with the wordmark inset: 708×522 of
   ink — the 1.356 aspect the design's width formula is written against — with
   96px transparent margin left/right and 189px top/bottom. So size the file up
   until the *ink* measures --ink-width, then pull the transparent margin back
   in, otherwise the mark renders a fifth too small and its empty lower margin
   shoves "Next release" down. Ratios: 708/900 = .7867, 96/900 = .1067,
   189/900 = .21. */
.hero__mark-img {
  --ink-width: min(30vw, calc(22vh * 1.356), 340px);
  display: block;
  width: calc(var(--ink-width) / .7867);
  height: auto;
  margin: calc(var(--ink-width) * -.267) calc(var(--ink-width) * -.1356);
}

.hero__release {
  margin: 20px 0 0;
  display: grid;
  justify-items: center;
  gap: 9px;
  animation: heroDissolve 1400ms ease-in-out 500ms both;
}

.eyebrow {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-semibold);
  font-size: 10px;
  line-height: 1.2;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--olive);
}

.hero__title {
  margin: 0;
  font-family: var(--font-serif-display);
  font-weight: var(--weight-serif-bold);
  font-size: clamp(20px, 3vw, 34px);
  line-height: 1.04;
  letter-spacing: -0.04em;
  color: var(--oxblood);
}

/* ---- Waitlist ---- */

.waitlist {
  margin-top: clamp(36px, 9vh, 96px);
  width: min(320px, 100%);
  pointer-events: auto;
  animation: heroDissolve 1400ms ease-in-out 1000ms both;
}

/* The glass card itself — same block whether it's showing the email form or
   the post-submit welcome line, so only the two children ever toggle.
   flex + align-items:center vertically centers whichever child is visible;
   padding alone left content top-anchored, with any min-height slack
   collecting below it instead of splitting evenly. */
.waitlist__panel {
  position: relative;
  display: flex;
  align-items: center;
  padding: 11px 14px;
  min-height: 44px;
  clip-path: polygon(8px 0, calc(100% - 13px) 0, 100% 10px, 100% calc(100% - 8px), calc(100% - 9px) 100%, 11px 100%, 0 calc(100% - 11px), 0 9px);
  background: linear-gradient(135deg, rgba(255,255,255,.5), rgba(255,255,255,.2));
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.65), inset 0 0 0 1px rgba(255,255,255,.25);
  transition: var(--transition-ui);
}

.waitlist__panel:focus-within {
  background: linear-gradient(135deg, rgba(255,255,255,.62), rgba(255,255,255,.3));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.7), inset 0 0 0 1px rgba(185,138,62,.4);
}

.waitlist__form {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 14px;
  min-height: 22px;
  flex: 1;
  min-width: 0;
}

/* Same face, size, weight, tracking, case and colour as .waitlist__submit —
   the welcome line reads as the button's own confirmation, not new copy. */
.waitlist__welcome {
  margin: 0;
  flex: 1;
  /* letter-spacing adds a trailing sliver of space after the last glyph with
     nothing to match before the first; text-align:center then centers that
     padded run, not the visible letters, reading as shifted off-centre.
     Pulling the run back in by one letter-space re-centres the glyphs. */
  margin-right: -.14em;
  text-align: center;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-semibold);
  font-size: 10px;
  line-height: 1.2;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--charcoal);
}

/* Same treatment as .waitlist__welcome (face/size/weight/tracking/case),
   just the design system's semantic error colour — sits below the still-
   visible form so the visitor can correct the address and retry. */
.waitlist__error {
  margin: 9px 0 0;
  margin-right: -.14em;
  text-align: center;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-semibold);
  font-size: 10px;
  line-height: 1.2;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--status-error);
}

.waitlist__input {
  width: 100%;
  box-sizing: border-box;
  background: transparent;
  border: 0;
  outline: none;
  padding: 0;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-regular);
  font-size: 12px;
  letter-spacing: .01em;
  color: var(--charcoal);
}

.waitlist__input::placeholder {
  color: rgba(28,23,14,.42);
}

/* The design system's global :focus-visible ring is meant for standalone
   controls; on the bare input it paints a hard cream/gold rectangle that the
   panel's clip-path slices. Focus is already signalled by :focus-within above. */
.waitlist__input:focus-visible {
  box-shadow: none;
}

.waitlist__submit {
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-semibold);
  font-size: 10px;
  line-height: 1.2;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--charcoal);
  transition: var(--transition-ui);
}

.waitlist__submit:hover {
  color: var(--oxblood);
}

.waitlist__tagline {
  margin: 9px 0 0;
  font-family: var(--font-sans);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .01em;
  font-weight: var(--weight-sans-semibold);
  color: var(--charcoal-60);
  text-align: center;
  /* The line runs just past the 320px column; split it evenly rather than
     dropping "worth sending." alone onto line two. */
  text-wrap: balance;
}

/* ---- Footer ---- */

.site-footer {
  position: relative;
  display: flex;
  align-items: flex-end;
}

/* Centred on the page independently of the mark, which stays put on the
   left — absolute + translateX rather than a grid/flex centering scheme,
   so the credit line never nudges the mark's own position. */
.site-footer__credit {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  margin: 0;
  white-space: nowrap;
  font-family: var(--font-sans);
  font-weight: var(--weight-sans-regular);
  font-size: 10px;
  letter-spacing: .01em;
  color: #999;
  opacity: .5;
}

.yew-mark {
  display: block;
  width: 32px;
  height: 32px;
  opacity: .85;
  /* The source PNG is dark ink on an opaque white ground, which reads as a
     white tile against the page. Multiply drops the white and keeps the ink. */
  mix-blend-mode: multiply;
}

a {
  color: var(--charcoal);
  border-bottom: 0;
}
a:hover {
  color: var(--oxblood);
}

/* ---- Responsive ---- */

/* iOS zooms the viewport on focus for inputs under 16px. */
@media (max-width: 640px) {
  .waitlist__input { font-size: 16px; }
}

@media (max-width: 380px) {
  .waitlist__form {
    grid-template-columns: 1fr;
    justify-items: start;
    gap: 10px;
  }
  .waitlist__submit {
    justify-self: start;
  }
}

/* Must win over .waitlist__form's own `display: grid` — same specificity,
   so this needs to come last in source order. */
[hidden] {
  display: none;
}
