/* Build 3, the etched placements. Loads after build3.css.

   Tests the three placements for the etched figure that don't put a headline
   over a bust, which is the one form that would cost trust:

     1. Nine plates in the measurement grid, one etched detail per measurement.
     2. A figure behind the closing line, large and low.
     3. Small fragments beside every section label.

   The hero deliberately keeps build 3's quiet dither field, because the whole
   point is testing the figure everywhere EXCEPT the hero. */

.hero, .close { overflow: hidden; }

.field { position: absolute; inset: 0; z-index: 0; opacity: 0; transition: opacity 1.6s ease .2s; }

/* ---- the fold headline, on its own size ----
   52 to 62 on desktop and 39 to 42 on a phone, Sabby's numbers, 2026-09-17.

   Scoped to the hero rather than changed at --head-size, which is the variable
   h1, h2 and .head all read. Moving that would have taken every section
   heading on every page up with it, and the apply and story headlines too.
   This is the one line he asked to look at.

   Worth knowing before this becomes permanent: Koe's page has exactly one
   heading size, and copying that is why the rest of this site does. The fold
   now sits a size above its sections, which is a real departure and a
   defensible one, since the fold is the only heading nobody scrolls to. */
.hero h1 { font-size: 62px; }

/* 42, not 44. 44 held two lines down to 390px and broke to three at 375, which
   is an iPhone SE and a 13 mini. 42 is the largest that keeps "Get your health"
   on one line at 375, so the headline reads the same shape on every phone
   anyone is actually holding. Desktop stays at 62. */
@media (max-width: 767px) {
  .hero h1 { font-size: 42px; }
}


/* ---- the wordmark, top left ----
   Absolute rather than in the flow, so the hero keeps its full-screen height
   and the dither field runs behind the mark instead of stopping under it.

   The width and the 34px match .pagenav in pages.css exactly. That is the
   point: three pages, one mark, one position. If one of them moves, move the
   other two. */
.topbar {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 3;
  padding: 34px 0;
}
.topbar .wrap { max-width: min(1180px, 92vw); }
.topbar .mark { display: block; width: max-content; }
.topbar .mark img { display: block; width: 112px; height: auto; }

@media (max-width: 640px) {
  .topbar { padding: 24px 0; }
  .topbar .mark img { width: 94px; }
}

/* ---- accent on the two small marks ----
   Sabby, 2026-09-17. The arrow and the separators are punctuation, so giving
   them the accent colours the movement and the rhythm of a line without
   colouring any of its words. The link's own hover still takes the whole thing
   to the accent, which is why the arrow inherits rather than sitting at a
   fixed colour. */
.textlink .arrow { color: var(--accent); transition: color .18s ease; }
.textlink:hover .arrow { color: inherit; }
.creds .sep { color: var(--accent); }


/* ---- the hero qualifier, under the button ----
   style.css sets .hero-count at 16px with 40px above it, which was right when
   it sat between the subhead and the button and had to hold that gap open.
   Under the button it is small print, so it comes down to 13px and tightens
   its tracking to match. Scoped to this page rather than changed in style.css,
   because the scratch builds still have it in the old position where the old
   size is correct.

   Grey, never the accent. The headline is the only colour above the fold and
   that stays true: a second accent down here would pull the eye off the
   button it is meant to qualify. */
.hero .hero-count {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 1.2px;
  margin: 22px 0 0;
}

/* On a phone it is given a measure so it breaks between its two sentences
   rather than running edge to edge. A single line of tracked caps spanning the
   full width of the screen reads as a rule, not as a note, and at 360px it was
   going to wrap in an arbitrary place anyway. */
@media (max-width: 640px) {
  .hero .hero-count {
    font-size: 12px;
    letter-spacing: 1px;
    margin-top: 20px;
    max-width: 24ch;
  }
}

.field.on { opacity: 1; }
.field canvas { display: block; width: 100%; height: 100%; }
#hero-field {
  -webkit-mask-image: radial-gradient(ellipse 70% 64% at 50% 48%,
    transparent 0%, transparent 52%, rgba(0,0,0,.4) 78%, #000 100%);
  mask-image: radial-gradient(ellipse 70% 64% at 50% 48%,
    transparent 0%, transparent 52%, rgba(0,0,0,.4) 78%, #000 100%);
}

/* ---------- 1. the nine plates ---------- */

.tile { padding-top: 0; overflow: hidden; transition: background .4s ease; }
/* Mouse only, for the same reason the JS gild is. A phone browser applies
   :hover on tap and then LEAVES IT THERE, because there is no pointer to move
   away, so on a phone these two rules left a tapped tile brightened and scaled
   up for good. Less visible than the orange sticking, same underlying mistake:
   the JS was gated on 2026-09-17 and the CSS beside it was not. */
@media (hover: hover) {
  .tile:hover { background: #070707; }
  .tile:hover .plate { opacity: 1; transform: scale(1.03); }
}
.tile .plate {
  position: relative;
  width: 100%;
  /* Square, because the nine engravings aren't one aspect ratio. The shader
     letterboxes each one inside the square with `contain`, which is what
     keeps a lung and a heart the same visual weight. */
  aspect-ratio: 1 / 1;
  margin: 18px 0 18px;
  opacity: .88;
  transition: opacity .45s ease, transform .6s cubic-bezier(.16,1,.3,1);
}
.tile .plate canvas { display: block; width: 100%; height: 100%; }

/* ---------- 2. the closing figure ---------- */

.close-figure {
  position: absolute;
  left: 50%;
  bottom: -6%;
  /* Wide and shallow. The whole reason this works where a figure didn't is
     that the artwork is horizontal: time on the x axis, under a centred
     headline, instead of a vertical body fighting it. */
  width: min(1240px, 96vw);
  height: 300px;
  margin-left: calc(min(1240px, 96vw) / -2);
  bottom: 54px;
  z-index: 0;
  opacity: 0;
  transition: opacity 2.2s ease;
  /* Solid at the bottom, dissolving as it rises, and pinched at the sides so
     it never ends on a vertical edge. The closing line sits in the clear
     upper third. */
  /* Feathered at the left and right ends only, so the line runs off the page
     instead of stopping on a vertical edge. No vertical fade: the chart is
     meant to be read, not sensed. */
  -webkit-mask-image: linear-gradient(to right,
    transparent 0%, #000 9%, #000 91%, transparent 100%);
  mask-image: linear-gradient(to right,
    transparent 0%, #000 9%, #000 91%, transparent 100%);
}
.close-figure.on { opacity: .92; }
.close-figure canvas { display: block; width: 100%; height: 100%; }

.close { padding-bottom: 420px; }   /* room for the chart under the button */
.close .wrap { position: relative; z-index: 1; }

/* The fragment markers that used to sit beside every section label are gone.
   Sabby's call: he didn't like them at any size. The labels are back to
   style.css's plain letter-spaced caps with nothing added. */

/* The hero background chooser is gone, and so is .close-switch, which styled a
   second chooser that no markup had referenced for some time. Dither, loud is
   the hero now and it is the only one. Sabby's call, 2026-09-17. */

@media (max-width: 767px) {
  .close { padding-bottom: 300px; }
  .close-figure { height: 210px; bottom: 40px; }
}

/* ---- two-column sections ----------------------------------------------
   Copy one side, an etched image the other. .split-flip puts the art first
   on desktop and nothing else changes, so the two sections mirror each
   other. Both stack to one column on mobile with the art underneath,
   because the copy is the thing that has to be read on a phone. */
.split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .82fr);
  gap: 92px;
  align-items: center;
  /* The site column is --col, about 732px, which is right for a single stack
     of copy and far too narrow for copy AND a picture. Two columns inside it
     left the art 304px wide, small enough to be missed entirely. These two
     sections get their own wider measure; every other section keeps --col. */
  max-width: min(1180px, 92vw);
}
.split-flip .wrap { grid-template-columns: minmax(0, .82fr) minmax(0, 1fr); }
.split-text { min-width: 0; }
.split-art  { min-width: 0; position: relative; }

.statue-turn,
.panel-turn { perspective: 1200px; }
.statue-field,
.panel-field {
  width: 100%;
  opacity: 0;
  transition: opacity 1.1s ease;
}
.statue-field { height: 520px; }
/* Same height as the sculpture, so the two sections mirror each other
   instead of one picture looking smaller than the other. */
.panel-field  { height: 520px; }
.statue-field.on { opacity: .92; }
.panel-field.on  { opacity: .88; }
.statue-field canvas,
.panel-field canvas { display: block; width: 100%; height: 100%; }

@media (max-width: 860px) {
  .split .wrap,
  .split-flip .wrap { grid-template-columns: 1fr; gap: 28px; }
  /* Art after the copy on a phone, whichever order it sits in on desktop. */
  .split-art { order: 2; }
  .split-text { order: 1; }
  .statue-field { height: 320px; }
  .panel-field  { height: 320px; }
}

/* The closing chart is gone, so the room that was reserved under the button
   goes with it. */
.close { padding-bottom: 120px; }
@media (max-width: 860px) { .close { padding-bottom: 96px; } }

/* ---- gold under the cursor -------------------------------------------
   Not a hover swap. A plate is 200px so its gold is a spark; the sculpture
   is 520px and a fully gold one is a wall, sitting right above a gold
   "Stay ahead" and next to the Apply button.

   Done with one blended overlay rather than a second shader mount, which
   matters: the nine plates and the hero already hold eleven WebGL contexts
   against a browser cap of about sixteen, so two more would be pushing it.

   multiply is the trick. Gold times white gives gold, so the etched dots
   warm up where the gradient is warm. Gold times black is still black, so
   the ground never lifts. Outside the circle the gradient is white, and
   white times anything is unchanged. */
.split-art,
.close-art {
  --mx: 50%; --my: 50%; --glow: 0; --gild-r: 230px;
  /* Two lines that are not optional. multiply only does the right thing when
     there is something opaque underneath it: against transparency it just
     paints its own colour, which is where the white boxes down the sides came
     from. An opaque black ground gives multiply black outside the dots, and
     isolate pins the blend to this box so it can never reach for the page. */
  background: #000;
  isolation: isolate;
}
.split-art::after,
.close-art::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  opacity: var(--glow);
  transition: opacity .45s ease;
  /* White is the neutral value for multiply, so everything past the circle is
     left exactly as it was. */
  background: radial-gradient(circle var(--gild-r) at var(--mx) var(--my),
              var(--accent) 0%, var(--accent-mid) 44%, #ffffff 76%);
}

/* On a touch screen the same overlay is driven by SCROLL POSITION instead of a
   cursor, so the warm patch travels down each picture as it passes. It used to
   be display:none here, because there is no pointer to follow.

   Two reasons this is safe on a phone where the tile gild was not. It writes
   three CSS custom properties on a scroll frame and touches no WebGL at all,
   where the tile gild ran a requestAnimationFrame loop per stuck tile pushing
   uniforms into eight live contexts. And --glow defaults to 0 on the element
   above, so if the script never runs nothing appears; nothing here depends on
   JS to stay hidden.

   Smaller circle, because the pictures are smaller. At 230px the patch covered
   most of a phone-width bust, which is the wall the cursor version exists to
   avoid. */
@media (hover: none) {
  .split-art,
  .close-art { --gild-r: 120px; }
}

/* ---- the closing heartbeat ----
   Under the button, not behind the words, and quiet: 0.3 is Sabby's number,
   picked off the slider in the preview. */
.close-art {
  position: relative;      /* so the gild overlay has something to sit in */
  margin: 54px 0 0;
  height: 170px;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.close-art.on { opacity: 1; }
.close-art canvas { display: block; width: 100%; height: 100%; }
/* Taller on a phone, and it works because the drawing changes too: under 640px
   the script loads the squeezed file, so the trace fills this box instead of
   hanging as a hairline in the middle of it. Raising the height on its own did
   nothing at all, which is worth remembering before anyone tries it again. */
@media (max-width: 860px) {
  .close-art { margin-top: 36px; height: 150px; }
}

/* ---- eight tiles, four across ----
   Nine in a 3x3 became eight, so four across and two down.

   And the section gets the WIDE measure, same as the two split sections. This
   was the point of dropping a tile and it's what the first pass got backwards:
   the grid stayed locked to the narrow --col column, so four tiles in the space
   of three just made every picture smaller. Widening the container is what
   makes the plates bigger. */
#what-we-set-up .wrap { max-width: min(1180px, 92vw); }
#what-we-look-at .grid,
#what-we-set-up .grid { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1080px) {
  #what-we-look-at .grid,
  #what-we-set-up .grid { grid-template-columns: repeat(2, 1fr); }
}
/* ---- the grid goes horizontal on a phone ----
   Sabby, 2026-09-17, after scrolling it on a real handset: eight square tiles
   stacked one per row is eight full screens of scrolling to read eight labels.
   Ruh's site lays its panels out as short rows and it reads far better.

   So under 560px the tile turns from a column into a row: small square plate
   on the left, number and label stacked on the right. Same markup, same eight
   canvases, no second set of assets. The plate goes from 100% of the tile
   width to a fixed 84px, which cuts the section's height by roughly two
   thirds.

   Worth knowing: the shader mount follows the element, so shrinking the plate
   in CSS re-renders it at the new size rather than scaling a bitmap down. The
   dither stays crisp. */
@media (max-width: 560px) {
  #what-we-look-at .grid,
  #what-we-set-up .grid { grid-template-columns: 1fr; }

  .tile {
    display: grid;
    grid-template-columns: 84px 1fr;
    column-gap: 20px;
    align-items: center;
    padding: 16px 18px;
    text-align: left;
  }
  /* The plate spans both text rows so the number and label centre against it. */
  .tile .plate {
    grid-column: 1;
    grid-row: 1 / span 2;
    width: 84px;
    height: 84px;
    margin: 0;
  }
  .tile em { grid-column: 2; grid-row: 1; align-self: end; margin-bottom: 7px; }
  .tile span { grid-column: 2; grid-row: 2; align-self: start; }
}

/* ---- footer ----
   A little air between the joke and the compliance line, and the company on
   the bottom. */
/* Three lines, two paragraphs. The joke is its own thought, so it gets real
   space under it. The disclaimer and the company are one block, so they sit
   tight together. */
footer .fineprint { margin-top: 42px; }
footer .colophon {
  margin-top: 7px;
  font-size: 12px;
  letter-spacing: .06em;
  color: rgba(232, 232, 232, .38);
}


/* ---- the accent hairline above the footer -----------------------------
   Sabby, 2026-09-17: the gold rule on the Apply page is the one motif he
   picked out unprompted, so it comes to the lander to separate the footer from
   the page. Same gradient and the same 0.5 opacity as pages.css .rule-gold, so
   the three pages carry one motif rather than three near-misses.

   It draws itself across on scroll instead of appearing, which is the same
   pseudo-element trick build3.css already uses on `section + section`: the
   border in style.css can't be animated, so it's made transparent and a
   scalable line is drawn in its place. Starting state hangs off .js, so if the
   script never runs the plain border is simply still there.

   'footer' had to be added to the observer list in build3.js. Note it sits in
   the last twelfth of the page, which is the exact dead strip that swallowed
   the compliance line, so it depends on the safety net that reveals whatever
   is left once the reader reaches the bottom. It is decorative, so that is an
   acceptable thing to depend on. The disclaimer underneath it still is not
   animated at all. */
.js footer { position: relative; border-top-color: transparent; }
.js footer::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(to right,
    transparent 0%, var(--accent) 14%, var(--accent) 86%, transparent 100%);
  opacity: .5;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1.15s cubic-bezier(.16, 1, .3, 1);
}
.js footer.is-in::before { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .js footer::before { transform: scaleX(1) !important; transition: none !important; }
}


/* ---- what we hear ----------------------------------------------------
   Type only, no art. The dots are the one piece of decoration and they are the
   accent, on Sabby's brief: no numbers, dots only, subtle.

   TWO COLUMNS BY HAND, and that is a deliberate reversal. This used to be one
   list on column-count, which rebalanced itself whenever a line was added and
   needed no maintenance. Good CSS, wrong idea. The left column is the man of
   40 in pain and the right is the man of 25 who feels fine, so the split
   carries meaning and must not be allowed to drift by one item.

   The section also runs wider than the 780px --col, because the quotes are
   real sentences rather than the old three-word fragments and two narrow
   columns would wrap most of them three times.

   No list markers: there is not a single bullet anywhere else on this site and
   the browser default would cheapen it, so the dot is drawn as a pseudo-element
   sized and coloured to match the page. */
#what-we-hear .wrap { max-width: min(980px, 92vw); }

#what-we-hear .sub {
  margin: -8px 0 0;
  font-size: 17px;
  line-height: 1.45;
  color: var(--fg-dim);
}

.reason-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 54px;
  margin-top: 40px;
}

/* Its own dim, not --label-dim. These sit under a section label that is already
   doing the small-caps job, so matching it exactly would give the section two
   headings of equal weight and no hierarchy at all. */
.col-head {
  margin: 0 0 20px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 3px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--fg-dim);
}

.reasons {
  list-style: none;
  margin: 0;
  padding: 0;
}

.reasons li {
  position: relative;
  padding-left: 22px;
  margin: 0 0 18px;
  font-size: 17px;
  line-height: 1.45;
  color: var(--fg);
}

.reasons li::before {
  content: '';
  position: absolute;
  left: 0;
  /* .62em rather than a pixel value, so the dot stays on the first line's
     optical centre if the type size ever changes. */
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

/* One column on a phone, and the two headings become the thing that keeps the
   two audiences apart once they are stacked. Gap grows, because a 38px break
   between groups has to read as bigger than the 15px between lines inside one. */
@media (max-width: 860px) {
  .reason-cols { grid-template-columns: 1fr; gap: 38px; margin-top: 32px; }
}

@media (max-width: 640px) {
  .reasons li { margin-bottom: 15px; }
  #what-we-hear .sub { font-size: 16px; }
}
}
