/* ========================================================================
   stepkeep — hero.css
   Hero, trust line, desk composition, hero motion, claims band.
   Split from css/components.css; load order in HTML preserves the cascade.
   ======================================================================== */

/* --- Hero -----------------------------------------------------------------
   One left-aligned column of copy over one full-width picture, rather than two
   half-width columns side by side. The headline was previously set inside a
   half-width column, where the page's own 56px h1 step came to twelve
   characters a line and had to be shrunk to fit — so the largest type on the
   site was never once shown at its size. Across the full measure each sentence
   is one line at 72px, and the picture below gets the whole width in return,
   which is what makes both artifacts in it legible.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  isolation: isolate;
  /* The bloom and the ruling are drawn past the page gutter. */
  overflow-x: clip;
  /* Vertical breathing room. A hero is the first thing a visitor sees and the
     only section with no content above it to borrow space from, so it is the
     one place on the page that can afford a full section-sized rhythm.

     The value is written as the gap plus the header, because it is a clearance
     and not the gap itself: the sticky header (--header-h) already occupies the
     top of the same viewport, and its height is air the reader counts as part of
     the hero. Writing it this way asks directly for the one figure that matters
     — the distance from the header's lower edge to the kicker's line box — and
     holds that figure steady as the clamp ramps. It is 52px of clear air on a
     phone and 92px on a laptop once the eyebrow's own half-line of leading is
     discounted. The old rule had no header term at all, so its 40/48 split left
     the section top-heavy; the same two edges are now 52px above against 72px
     below on a phone, and 92px against 112px on a laptop.

     One band is the exception. Between roughly 44.5rem and 48.75rem the desktop
     nav wraps to a second line and the header becomes 76.8px tall, which eats
     12px of this padding; the gap there is 42px rather than 52px. Substituting
     the header's own height for that band would mean three more clamped media
     queries tracking a wrap that a nav fix should remove anyway, so it is left
     documented — 42px is still clear air, and the number to change if the wrap
     is ever repaired is --header-h.

     The ramp reaches its 96px end at 1280px and is deliberately slow. Padding is
     the one thing on the page that should not track the viewport closely: a hero
     that gains 40px of air between 1024px and 1440px looks like it is still
     loading. */
  padding-top: max(clamp(3.5rem, 7.5vw, 6rem) + var(--header-h), 3.5rem);
  padding-bottom: clamp(4.5rem, 8vw, 7rem);
}

/* Ruled paper. Hairlines on a 2.25rem rhythm, faded out before they reach the
   claims so the band below reads on plain stock. The direction is "a well-made
   document"; this is the cheapest possible way to say it,
   and it costs no bytes and no requests. */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: linear-gradient(var(--rule) 1px, transparent 1px);
  background-size: 100% 2.25rem;
  opacity: 0.5;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 34%, transparent 62%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 34%, transparent 62%);
  pointer-events: none;
}

/* A warm bloom behind the page, in Marker at the wash opacity the tokens
   already define. It is the only light source on the page, and it sits under
   the one object this section is asking to be looked at: the printed guide. */
.hero::after {
  content: '';
  position: absolute;
  z-index: -2;
  top: 22%;
  right: -18%;
  width: min(64rem, 110vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, var(--marker-wash) 0%, transparent 60%);
  /* A wash of a saturated yellow over paper; over the dark surface the same
     wash is a haze, so the dark palettes drop it to a hint. */
  opacity: var(--hero-bloom, 1);
  pointer-events: none;
}

.hero__lead {
  /* The lead copy column and the desk below it are two different objects: one
     is read, the other is looked at. 48px on a phone, 80px on a laptop — the
     loose tier, so the picture starts a new group rather than trailing the
     trust line. It also has to stay looser than the 24px between the buttons
     and the trust row, or the desk would bind to the button instead of the
     trust row binding to it. */
  margin-bottom: clamp(3rem, 6vw, 5rem);
}

/* The kicker belongs to the headline, not to the page. Measured optically, the
   old 16px margin left 25px of air under the eyebrow against 32px under the
   headline — only a 1.2x difference, so the label read as a fourth line of the
   lede rather than as a name for the heading above it. At 8px the same two gaps
   are 17px and 32px: the kicker is plainly attached to what it labels, and the
   heading is plainly separated from the sentence it introduces.

   Raised to 12-16px with the rest of the hero's rhythm. 8px is the tight tier
   for an icon beside a label; an uppercase 14px line above a 30-72px headline
   is two different levels of type, and at 8px the descender of the headline's
   cap-height lede sat almost on the eyebrow. The gap still has to stay well
   under the headline-to-lede gap for the label to keep reading as a label:
   it is 16px against 40px on a laptop, a ratio of 2.5. */
.hero__lead .eyebrow {
  margin-bottom: clamp(var(--sp-3), 1vw, var(--sp-4));
}

.hero__title {
  /* 32px minimum, because this is a heading immediately followed by a
     paragraph and the heading owns the space to its copy. The old flat 24px
     was a fixed length under type that grows from 30px to 72px, so the largest
     headline on the site had the same gap under it as a 320px phone did.
     The clamp ends at 40px, keeping it inside the 32-48px band for
     heading-to-copy while staying visibly tighter than the 56px above the
     button, which is what keeps the lede bound to the headline rather than
     floating between the two. */
  margin: 0 0 clamp(2rem, 2.5vw, 2.5rem);
  /* Display size. The vw term is tuned so "The guide writes itself." holds one
     line from 320px up; the two sentences are broken by hand, because the break
     is the argument — one line is the work, the other is what it costs you. */
  font-size: clamp(1.9rem, 6.6vw, 4.5rem);
  line-height: 1.04;
  letter-spacing: -0.038em;
  /* `balance` would pull a word across the hand-written break to even the two
     lines out, which is the one thing that break exists to prevent. */
  text-wrap: pretty;
}

/* The highlighter at display size. The utility's flat 3px stroke is drawn for
   17px body copy; here it is scaled to the type and pulled up over the baseline
   so it reads as a pass of a marker across the words rather than as a rule
   underneath them. The descenders sit in it, which is what a real one does.

   The offset is measured from the bottom of the inline box rather than as a
   percentage of it, so the stroke lands on the baseline at every size instead
   of drifting under the descenders as the type grows. */
.hero__title .marked {
  background-size: 100% 0.32em;
  background-position: left 0 bottom 0.35em;
  padding-inline: 0.04em;
  padding-bottom: 0;
}

/* On the dark palette a half-height stroke cannot work. Ink there is a light
   mint, which on this yellow is a contrast ratio of about 1.5, and flipping the
   text to --on-marker instead leaves the half of each letter standing above the
   stroke sitting on the dark page, invisible. So in dark the same marker covers
   the words outright, and the text on it flips the way --on-marker already
   flips for selection. Written twice, per the note in tokens.css: the media
   query has to keep working with scripting off, and the attribute has to win
   when the header switch is used. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .hero__title .marked {
    background-size: 100% 0.96em;
    background-position: left 0 bottom 0.28em;
    color: var(--on-marker);
  }
}

:root[data-theme='dark'] .hero__title .marked {
  background-size: 100% 0.96em;
  background-position: left 0 bottom 0.28em;
  color: var(--on-marker);
}

.hero__lede {
  /* The largest gap inside the hero is the one above the form, so the button is
     the end of the sentence rather than one more line of it. At 32px it merely
     matched the headline's gap and the eye had no destination; the clamp takes
     it to 48px on a laptop and keeps 32px on a phone, where the measure is
     short and the button is already the only thing under the words. */
  margin: 0 0 clamp(var(--sp-6), 3.5vw, var(--sp-7));
  /* Narrower than the headline on purpose: the headline is a poster and wants
     the page, the sentence under it is prose and wants a measure. */
  max-width: 44rem;
  font-size: clamp(1.0625rem, 1.5vw, 1.375rem);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

/* The sentence that explains why this page is short, and only the coming-soon
   page has it: the finished page goes straight from the lede to the buttons,
   because a visitor who has already decided needs nothing in between. */
.hero__note {
  max-width: 44rem;
  margin: 0 0 var(--sp-6);
  color: var(--slate);
}

/* --- Trust line -----------------------------------------------------------
   Directly under the button, not below the fold. The two things it settles are
   asked in the second between reading the headline and reaching for Install,
   and an answer that arrives after a scroll has arrived too late. */

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-6);
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: var(--step--1);
  color: var(--slate);
}

.trust__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.trust__icon {
  flex: none;
  /* Moss, the palette's "saved locally" green. Marker is spent on the headline
     and on the ring in the screenshot, and is not reused here. */
  color: var(--moss);
}

/* --- The desk ---------------------------------------------------------------
   The screen the task was done on, and the printed page it became, arranged as
   they would be on a desk: the page put down over the screen's right edge, a
   degree or two off square, and standing proud of the window's foot. The page
   is the product, so it is in front and it is big enough to read. The window
   is cropped by nothing and carries its ring at the left, where the page cannot
   reach it.

   Everything is sized from the container, so the two objects keep their
   relationship at every width until the phone breakpoint, where they stack. */

.desk {
  position: relative;
  /* Room for the page to hang below the window. The page is sized from the
     container's width, so its overhang is too; a fixed length here would let
     the file tag land on the caption at one width and float at another. */
  padding-bottom: calc(7% + 1rem);
  /* The tilted page throws a shadow past its own box; the hero clips the
     x-axis already, this is only to keep it from being cut on the y. */
  padding-top: 0.5rem;
}

.desk__screen {
  position: relative;
  z-index: 1;
  width: 74%;
  margin: 0;
}

.desk__screen .shot__frame {
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(22, 58, 46, 0.06), 0 24px 56px rgba(22, 58, 46, 0.14);
  overflow: hidden;
}

/* "0 B uploaded" in the window chrome, in Moss, beside the recording light.
   The chrome bar is the one part of this picture the page draws itself, and
   this is the fact the whole product rests on, stated where a network panel
   would state it. */
.shot__net {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-right: 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 500;
  color: var(--moss);
  white-space: nowrap;
}

.shot__net-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--moss);
}

.desk__page {
  position: absolute;
  z-index: 2;
  right: 0;
  /* Below the window's chrome bar, so the recording light and the upload
     count stay in view. */
  top: 8%;
  width: 40%;
  margin: 0;
  transform: rotate(1.6deg);
  transform-origin: 50% 40%;
}

/* The export is white paper and stays white paper in both colour schemes. A
   document that changes colour with the reader's OS is not a document. The
   sheet shows the head of the page at a readable scale; the rest of an A4 with
   one step on it is margin, and the fade at the foot says the page goes on. */
.desk__sheet {
  display: block;
  position: relative;
  overflow: hidden;
  aspect-ratio: 0.84;
  background: #fff;
  border: 1px solid rgba(22, 58, 46, 0.14);
  border-radius: 2px;
  box-shadow:
    0 1px 2px rgba(22, 58, 46, 0.08),
    0 6px 14px rgba(22, 58, 46, 0.08),
    0 30px 70px rgba(22, 58, 46, 0.22);
}

.desk__sheet::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 18%;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 85%);
  pointer-events: none;
}

.desk__img {
  display: block;
  width: 100%;
  height: auto;
}

/* The file label, pinned to the sheet's foot like a sticky tab. */
.desk__tag {
  position: absolute;
  left: 1rem;
  bottom: -0.9rem;
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  white-space: nowrap;
  padding: 0.38rem 0.7rem 0.4rem;
  background: var(--ink);
  color: var(--on-ink);
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  box-shadow: var(--shadow-card);
}

.desk__tag svg {
  align-self: center;
}

.desk__tag-meta {
  opacity: 0.7;
}

.desk__cap {
  margin-top: var(--sp-4);
  /* Under the window, never under the page. */
  max-width: 74%;
  font-size: var(--step--1);
  color: var(--slate);
  text-wrap: pretty;
}

/* --- Hero motion ------------------------------------------------------------
   Gated on the same html[data-anim] switch as the rest of the page, so with
   scripting off, or reduced motion on, nothing here moves and nothing is ever
   transparent. The copy rises in reading order, the marker is drawn across
   the second line, the window arrives, and then the page prints itself from
   the top down, which is the headline happening once, in front of the reader.
   Everything is finished inside two seconds. */

@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes hero-draw {
  from { background-size: 0% var(--stroke-h); }
  to { background-size: 100% var(--stroke-h); }
}

/* The clip includes a margin so the sheet's shadow prints with it. */
@keyframes hero-print {
  from {
    clip-path: inset(-12% -20% 112% -20%);
    transform: translateY(-14px) rotate(1.6deg);
  }
  to {
    clip-path: inset(-12% -20% -40% -20%);
    transform: rotate(1.6deg);
  }
}

@keyframes hero-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.hero__title .marked {
  --stroke-h: 0.32em;
}

html[data-anim='on'] .hero__lead > * {
  animation: hero-rise 0.7s var(--ease) both;
}

html[data-anim='on'] .hero__lead > :nth-child(2) { animation-delay: 70ms; }
html[data-anim='on'] .hero__lead > :nth-child(3) { animation-delay: 140ms; }
html[data-anim='on'] .hero__lead > :nth-child(4) { animation-delay: 210ms; }
html[data-anim='on'] .hero__lead > :nth-child(5) { animation-delay: 280ms; }

/* The stroke is drawn in light only. In dark the marker covers the words and
   the text on it is dark, so a stroke growing from nothing would leave the
   words invisible until it arrived. */
html[data-anim='on']:not([data-theme='dark']) .hero__title .marked {
  animation: hero-draw 0.75s var(--ease) 0.5s both;
}

@media (prefers-color-scheme: dark) {
  html[data-anim='on']:not([data-theme='light']) .hero__title .marked {
    animation: none;
  }
}

html[data-anim='on'] .desk__screen {
  animation: hero-rise 0.8s var(--ease) 0.25s both;
}

html[data-anim='on'] .desk__page {
  animation: hero-print 1.05s cubic-bezier(0.2, 0.7, 0.2, 1) 0.8s both;
}

/* --- The three claims ------------------------------------------------------
   A three-column band across the foot of the hero, on one rule, so the row
   reads as the summary line of a document rather than as a table. */

.hero__band {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(1.5rem, 3vw, 2rem);
  border-top: 1px solid var(--rule-strong);
}

.claims {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  list-style: none;
  padding: 0;
  margin: 0;
}

.claim {
  display: block;
  font-size: var(--step--1);
}

.claim__title {
  display: block;
  margin-bottom: 0.15rem;
  font-weight: 600;
  color: var(--ink);
}

.claim__body {
  display: block;
  color: var(--slate);
  text-wrap: pretty;
}

