/* Evergrove — the front page scroll story.

   Written phone first. The base rules below ARE the phone layout; the media
   queries at the bottom of each block widen it out. The test that matters is
   that on a 390x760 screen each beat is whole: you never have to scroll to
   find the other half of the thought you are reading. The two endings in
   particular stay side by side at every width, because "six feet under" and
   "ashes" are one idea and stacking them breaks it.

   Layout only. Colour, type and the .specimen plate convention come from
   evergrove.css; nothing here redefines a brand value. */

/* Each beat lands at the top of the window rather than halfway, so you are
   never looking at the foot of one and the head of the next at the same
   time. Proximity rather than mandatory: it corrects a near miss and
   otherwise leaves scrolling alone. */
html {
  scroll-snap-type: y proximity;
  /* the whole sticky stack, not just the menu. With only --head-h here the
     first beat snapped 41px down, scrolling the strip out from under itself
     and frosting the menu before anyone had touched the page. */
  scroll-padding-top: var(--chrome);
}
.beat { scroll-snap-align: start; }

/* ===== the beat ======================================================== */
.beat {
  min-height: calc(100svh - var(--chrome));
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
  padding-block: clamp(34px, 7vh, 120px);
  /* the note stands above the stamp on the right; nothing may sit under it */
  padding-bottom: max(clamp(34px, 7vh, 120px), calc(var(--card-rise) + 14px));
  position: relative;
}
/* The beats share the header's container. They were on a wider one, which put
   the headline to the left of the wordmark on any screen over 1320px: the
   left edge of the page has to be a single line. */

.say {
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(26px, 7.8vw, 44px);
  line-height: 1.07;
  letter-spacing: -0.012em;
  max-width: none;
  margin: 0;
  text-wrap: balance;
}
.say em { font-style: italic; }

@media (min-width: 900px) {
  .say { font-size: clamp(40px, 4.15vw, 64px); }
}

/* ===== beat 1 — the hero ===============================================
   Two compositions, not one that shrinks.

   The headline and the tree are INDEPENDENT siblings in a single column.
   They used to be the two cells of a 0.38fr/1fr grid, which meant the
   headline's width was a fraction of the row and the tree was centred inside
   its own column: each was positioned relative to the other, so the headline
   drifted whenever the tree changed. Here the headline anchors itself to the
   content margin and the tree centres itself on the page, and neither knows
   the other exists.

   Phone     nav, air, tree, headline under it, air below.
   Desktop   headline top left, a large expanse of nothing, tree growing out
             of the lower centre. space-between does that without a single
             hand-placed offset. */
.open {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 4vh, 42px);
}

/* Anchored to the content margin, never to the tree. The measure is set in
   em of the heading's own size, so it keeps the same two-line break at every
   size instead of being a fraction of whatever is beside it. */
.open__say { align-self: start; }
.open__say .say {
  max-width: 5.6em;
}

.open__art { align-self: center; }
.open__art img { display: block; width: 100%; height: auto; }

/* --- phone: tree above the headline, upper middle of the screen --------- */
.beat--open {
  justify-content: center;
  /* Asymmetric: the group sits above centre, as the reference does, without
     being positioned out of flow. */
  padding-top: clamp(16px, 3.5vh, 40px);
  padding-bottom: clamp(74px, 16vh, 170px);
}
.open__art {
  order: -1;                                  /* h1 stays first in the DOM */
  /* Measured off the reference: the plate runs nearly the full screen, a
     little past the page margin on each side. */
  width: min(94vw, 470px);
}

/* --- desktop: the editorial composition -------------------------------- */
@media (min-width: 900px) {
  .beat--open {
    justify-content: stretch;
    padding-top: clamp(26px, 5vh, 64px);
    /* the note stands above the stamp on the right; the plate must clear it */
    padding-bottom: max(clamp(16px, 2.6vh, 40px), calc(var(--card-rise) + 14px));
  }
  /* Both children occupy the SAME cell and each anchors itself: the headline
     to the top left of the content area, the plate to the bottom centre of
     the page. Stacking them in flow meant the plate could only have the
     height the headline did not use, which is why it was small. Overlapping
     cells cost nothing here because the top corners of the plate are empty
     sky. */
  .open {
    display: grid;
    grid-template-areas: "hero";
    flex: 1;
    gap: 0;
  }
  .open__say, .open__art { grid-area: hero; }
  .open__say { align-self: start; justify-self: start; }
  .open__say .say { font-size: clamp(40px, 4.15vw, 64px); }
  .open__art { order: 0; align-self: end; justify-self: center; width: auto; }
  .open__art img {
    width: auto;
    /* 60vw alone kept growing past the content column on a wide screen, and
       the canopy spread left until it sat behind the headline. The px cap
       stops the plate at roughly the width of the page's own measure. */
    /* 1400px is the plate's own width, so it is never upscaled. The old
       940px cap left a 354px hole between the headline and the canopy on a
       2560px screen: the plate had run out of permission, not room. */
    max-width: min(70vw, 1400px);
    /* clears the header, the stamp and the note above it */
    max-height: calc(100svh - var(--chrome) - 64px);
  }

  /* Where the screen is tall enough to hold both, the canopy stops just under
     the headline instead of rising behind it: the beat's own paddings, the
     chrome, and two lines of the display face at its own clamp, plus air.
     Below this height there is not room for both, and the plate keeps the
     overlap it has always had, where its top corners are empty sky. */
  @media (min-height: 880px) {
    .open__art img {
      max-height: calc(100svh
        - clamp(16px, 2.6vh, 40px)
        - var(--chrome)
        - clamp(26px, 5vh, 64px)
        - 2.14 * clamp(40px, 4.15vw, 64px)
        - 26px);
    }
  }

  /* While the consent bar is up it covers the foot of the first screen, and
     the plate is anchored there. Lifting the beat's floor by the bar's own
     height moves the plate above it, and the same subtraction comes off the
     plate's ceiling so it shrinks to fit rather than pushing the headline.
     The envelope is already hidden in this state, so its clearance is not
     needed and the padding can be the bar alone. */
  html.has-cc .beat--open {
    padding-bottom: calc(var(--cc-h, 0px) + clamp(16px, 2.6vh, 40px));
  }
  html.has-cc .open__art img {
    max-height: calc(100svh - var(--chrome) - 64px - var(--cc-h, 0px));
  }
}

/* ===== beat 2 — the two endings ========================================
   Stacked on a phone and side by side from 900px, per the references. Both
   still land on one phone screen, because stacking them at about two thirds
   of the screen width costs less height than it looks like it should. */
.endings__say {
  text-align: center;
  margin-inline: auto;
}
@media (min-width: 900px) { .endings__say { font-size: clamp(34px, 3.9vw, 62px); } }

.endings {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(28px, 5.5vh, 70px);
  margin-top: clamp(30px, 5vh, 70px);
  align-items: end;
  justify-items: center;
}
.ending { width: clamp(200px, 72%, 360px); text-align: center; }
.ending img {
  width: auto;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
  /* stacked, so each gets half of whatever the slot leaves */
  max-height: calc((100svh - var(--chrome) - 284px) / 2);
}
@media (min-width: 900px) {
  .endings { grid-template-columns: 1fr 1fr; }
  .ending { width: 100%; max-width: 560px; }
  /* sized off the slot between the header and the stack, not off the
     viewport, so the pair always fits one screen */
  .ending img { width: auto; max-width: 100%; margin-inline: auto;
    max-height: calc(100svh - var(--chrome) - var(--card-rise) - 250px); }
}

.ending figcaption {
  margin-top: clamp(14px, 2.8vh, 28px);
  font-family: var(--mono);
  font-size: clamp(10px, 2.8vw, 19px);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
}
@media (min-width: 900px) {
  .ending figcaption { font-size: clamp(13px, 1.4vw, 19px); letter-spacing: .20em; }
}

/* ===== beat 3 — the turn and the catalogue =============================
   On a phone: the turn, then the plate, then the choice under it. The heading
   and the choice both live inside .cat__words, so on a phone that wrapper
   steps out of the way with display:contents and all three order as siblings.
   On a wide screen they sit side by side. */
.cat { display: grid; gap: clamp(18px, 3vh, 46px); }
.cat__words { display: contents; }
.cat .say   { order: 1; }
.cat__stage { order: 2; }
.cat__pick  { order: 3; }

.cat__pick { margin-top: clamp(20px, 3.4vh, 46px); }

.cat__lead {
  font-family: var(--disp);
  font-style: italic;
  font-size: clamp(25px, 6.6vw, 48px);
  line-height: 1.1;
  color: var(--ink);
  margin: 0 0 clamp(10px, 1.6vh, 22px);
  max-width: none;
}

/* Every option occupies the same grid cell, so the box is as tall as the
   longest of them and advancing never reflows the page. */
.cat__label {
  display: grid;
  margin: 0;
  max-width: none;
  font-family: var(--mono);
  font-size: clamp(13px, 3.6vw, 25px);
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--ink);
}
.cat__label span {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(5px);
  transition: opacity .45s ease-out, transform .45s ease-out;
}
.cat__label span.is-active { opacity: 1; transform: none; }

.cat__rule {
  height: 0;
  border: 0;
  border-top: 1.5px dotted var(--ink-soft);
  opacity: .62;
  margin: clamp(8px, 1.2vh, 16px) 0 0;
  width: min(100%, 460px);
}

/* Aspect ratios run from a 1400x2224 terrarium to a 1400x961 cemetery, so the
   box is fixed and each plate is contained in it and floored. */
.cat__stage {
  position: relative;
  /* off the slot the stack leaves, so the beat lands on one screen */
  /* The slot left once the headline and the picker have taken theirs. The
     picker replaced a single arrow, so it needs about 80px more than the
     arrow did and this constant grew to match. */
  min-height: clamp(132px, calc(100svh - var(--chrome) - 500px), 340px);
}
.cat__stage .specimen {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .9s ease-out;
}
.cat__stage .specimen.is-showing { opacity: 1; }
.cat__stage .specimen img {
  opacity: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom center;
}

@media (min-width: 900px) {
  .cat {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    gap: clamp(22px, 2.4vw, 42px);
    align-items: stretch;
  }
  .cat__words { display: flex; flex-direction: column; }
  .cat .say, .cat__stage, .cat__pick { order: 0; }
  /* The turn sits at the top, the choice at the bottom, and the space
     between them is the pause. */
  .cat__pick { margin-top: auto; padding-top: clamp(28px, 5.5vh, 76px); }
  /* 70px was the room the old arrow needed under the stage. The picker is
     taller, so the stage gives that back or the beat outgrows the screen. */
  .cat__stage { order: 0; min-height: clamp(240px, calc(100svh - var(--chrome) - 118px), 694px); }
}

/* ===== the arrow =======================================================
   The only control, so it has to ask to be used. It nudges right, leaves,
   and comes back from the left: the gesture of "and then". ============= */
.arrow {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(62px, 17vw, 86px);
  height: clamp(36px, 10vw, 48px);
  margin-top: clamp(18px, 2.8vh, 38px);
  padding: 0;
  background: none;
  border: 1.5px solid var(--ink-soft);
  border-radius: 999px;
  color: var(--ink);
  cursor: pointer;
  position: relative;
  transition: border-color .3s, background-color .3s, color .3s;
}
.arrow svg { width: 42%; height: auto; display: block; overflow: visible; }
.arrow__head { animation: arrow-pass 4.4s ease-in-out infinite; }

@keyframes arrow-pass {
  0%, 56%   { transform: translateX(0);     opacity: 1; }
  69%       { transform: translateX(11px);  opacity: 0; }
  70%       { transform: translateX(-11px); opacity: 0; }
  83%, 100% { transform: translateX(0);     opacity: 1; }
}

/* A ring that opens out of the button on the same cadence, so the prompt is
   visible even at the edge of vision. */
.arrow::after {
  content: '';
  position: absolute;
  inset: -1.5px;
  border: 1.5px solid var(--midnight);
  border-radius: inherit;
  opacity: 0;
  animation: arrow-ring 4.4s ease-out infinite;
  pointer-events: none;
}
@keyframes arrow-ring {
  0%, 56%  { transform: scale(1);    opacity: 0; }
  64%      {                         opacity: .34; }
  86%,100% { transform: scale(1.34); opacity: 0; }
}

.arrow:hover, .arrow:focus-visible {
  background: var(--forest);
  border-color: var(--forest);
  color: var(--beige);
}
/* Once someone has used it, it stops asking. */
.arrow:hover .arrow__head,
.arrow:focus-visible .arrow__head,
.cat.is-taken .arrow__head { animation: none; }
.arrow:hover::after,
.arrow:focus-visible::after,
.cat.is-taken .arrow::after { animation: none; opacity: 0; }
.arrow:hover .arrow__head { transform: translateX(4px); transition: transform .3s; }

@media (prefers-reduced-motion: reduce) {
  .arrow__head, .arrow::after { animation: none; }
  .arrow::after { opacity: 0; }
  .cat__label span, .cat__stage .specimen { transition: none; }
}

/* ===== the exit ======================================================== */
.exit { text-align: center; }
.exit p { margin-inline: auto; }
.exit__row {
  margin-top: clamp(24px, 3.6vh, 44px);
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}


/* ===== a note from the founder =========================================
   A page torn off a pad and clipped down: ring holes punched through the
   top edge, faint rules, typewriter throughout. The holes are cut with a
   mask so the ground shows through them.

   The type is var(--mono) for now. When the handwriting face exists this
   is the one place it should go. */
.beat--note {
  padding-block: clamp(50px, 9vh, 120px) clamp(30px, 5vh, 70px);
  display: flex;
  justify-content: center;
}

.scrap {
  position: relative;
  margin: 0;
  width: min(100%, 520px);
  transform: rotate(-1.1deg);
}

.scrap__paper {
  --hole: 10px;
  --hole-pitch: 26px;
  --tear: 15px;
  position: relative;
  z-index: 1;
  padding: calc(var(--tear) + 26px) clamp(22px, 5vw, 38px) clamp(24px, 4vh, 34px);
  color: var(--ink);
  background-color: #E2DBCA;
  /* the rules, starting below the torn edge */
  background-image: repeating-linear-gradient(180deg,
    #0000 0 25px, rgba(45, 32, 17, .105) 25px 26px);
  background-position: 0 calc(var(--tear) + 18px);
  box-shadow: 0 10px 26px rgba(45, 32, 17, .15);

  /* holes along the top only: the first layer punches them, the second
     covers everything below the torn band, and the two add together */
  -webkit-mask-image:
    repeating-linear-gradient(90deg, #0000 0 var(--hole), #000 var(--hole) var(--hole-pitch)),
    linear-gradient(#0000 0 var(--tear), #000 var(--tear));
  -webkit-mask-size: var(--hole-pitch) var(--tear), 100% 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
  -webkit-mask-position: 7px 0, 0 0;
          mask-image:
    repeating-linear-gradient(90deg, #0000 0 var(--hole), #000 var(--hole) var(--hole-pitch)),
    linear-gradient(#0000 0 var(--tear), #000 var(--tear));
          mask-size: var(--hole-pitch) var(--tear), 100% 100%;
          mask-repeat: repeat-x, no-repeat;
          mask-position: 7px 0, 0 0;
}

.scrap__text {
  font-family: var(--mono);
  font-size: clamp(12.5px, 3.1vw, 14px);
  line-height: 1.85;
  color: var(--ink);
  margin: 0;
  max-width: none;
}

.scrap__more {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  margin-left: .35em;
  font: inherit;
  color: var(--midnight);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.scrap__more:hover { color: var(--oxblood); }
/* it does nothing without the dialog, so it is not offered */
html:not(.has-dialog) .scrap__more { display: none; }

/* the clip, front and back, same trick as the messages bar */
.scrap__clip {
  position: absolute;
  right: clamp(26px, 8vw, 58px);
  top: -32px;
  height: 84px;
  width: auto;
  transform: rotate(13deg);
  filter: drop-shadow(1.5px 2.5px 2.5px rgba(45, 32, 17, .26));
  pointer-events: none;
}
.scrap__clip--back  { z-index: 0; }
.scrap__clip--front {
  z-index: 2;
  -webkit-mask-image: linear-gradient(90deg, #000 0 50%, #0000 50%);
          mask-image: linear-gradient(90deg, #000 0 50%, #0000 50%);
}

@media (prefers-reduced-motion: reduce) {
  .scrap { transform: none; }
}

/* The closing statement now carries the section on its own, so it sits above
   body size without reaching display size: a centred didone paragraph this
   long is hard to read, and this one has to be read. The measure is held
   near 46ch so it breaks to four or five lines rather than a wide block. */
.exit__say {
  font-family: var(--text);
  /* a step down from the single sentence this used to hold: the passage is now
     five sentences, and 25px centred over that length reads as a wall */
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.6;
  max-width: 58ch;
  text-wrap: pretty;
  color: var(--ink);
}
.exit__say--after { margin-top: clamp(16px, 1.8vw, 22px); }

/* Squared off rather than centred: both edges flush, which needs hyphenation
   or a justified measure this long opens rivers between the words. The buttons
   come back to the text block's own left edge so the group reads as one
   column rather than a block with something centred under it. */
.exit__say { text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
.exit__say:last-of-type { text-align: left; }   /* a short last para justifies badly */
/* One button now, and it sits centred under the squared passage rather than
   pinned to its left edge. */
.exit .exit__row { justify-content: center; }

/* the invitation under the row of possibilities */
.cat__go { margin-top: clamp(30px, 4.4vh, 54px); }
@media (max-width: 559px) {
  /* the full sentence will not hold one line on a phone at the button's
     tracking, and two lines of tracked caps in a pill reads as a paragraph */
  .cat__go .btn { padding-inline: 16px; font-size: 11px; letter-spacing: .08em; }
}

/* The hero's plate is anchored to the bottom of its beat, so when the next
   beat snaps to the top its canopy is still inside the menu band and frosts
   it. The overlap is exactly the menu row less the hero's bottom padding, so
   the snap is pulled down by that much plus a little air. A negative
   scroll-margin shrinks the snap box from the top, which lands the beat
   slightly further down rather than slightly higher. */
@media (min-width: 900px) {
  .beat--open + .beat {
    scroll-margin-top: calc(clamp(16px, 2.6vh, 40px) - var(--head-h) - 4px);
  }
}

/* The closing beat snapped with the catalogue's button and plates still inside
   the menu band, so the bar frosted against the beat above it. Pulling the
   snap down clears them. Negative, because a negative scroll-margin shrinks
   the snap box from the top and lands the beat slightly further down. */
@media (min-width: 900px) {
  .exit { scroll-margin-top: -44px; }
}
