/* ============================================================
   /voice-ai/ — THE CALL, OPENED UP.

   This page has one artefact and everything else on it is support. The product
   is a phone call, so the page shows a phone call: one ordinary job, from the
   first ring to the text message, with the elapsed clock down the left.

   ⚠️ WHY A TRANSCRIPT AND NOT A FEATURE LIST. Everyone selling voice AI writes
   the same four bullets — answers 24/7, books appointments, natural voice,
   never misses a call. A reader has no way to tell one of those lists from
   another, so the list argues for the category and not for us. A call they can
   read line by line is checkable: they can see it get interrupted, see it ask
   rather than guess, see the diary read before a time is offered. That is the
   difference the bullets are trying to claim.

   ⚠️ THE SYSTEM'S OWN ROWS ARE INTERLEAVED, NOT PARALLEL. An earlier shape had
   the words on the left and "what it was doing" in a rail on the right, which
   reads as two things happening at once. They are not two things. The diary is
   read DURING the sentence before the slot is offered, and putting that row in
   the same column, at its own second, is the whole claim: it booked from live
   data inside the call rather than writing a message for someone to action.

   Loaded only by /voice-ai/. Anything here that a second capability page turns
   out to need moves up to page.css rather than being copied.
   ============================================================ */

/* ============================================================
   THE HERO — A FLOATING PANEL.

   Founder-directed, and this is the third attempt: "can you try having a
   floating hero and the bottom of the floating hero covered with waveform to
   the edge that moves."

   ⚠️ WHAT THE TWO REJECTED VERSIONS GOT WRONG — both worth keeping written
   down. The first was a full-bleed near-black field with the type in the
   top-left corner, one button and a dead right half: "nothing elegant and
   beautiful about it", and true. The second fixed that by building on home's
   own hero component — warm ramp, centred type, two job cards cropped by the
   frame. It solved the elegance and failed differently: "i did not mean copy
   the design". A product page that reproduces the home page is not a page, it
   is a reprint.

   So neither. A panel that FLOATS on the page ground — inset on all four
   sides, heavily rounded, with a real shadow under it — dark, because the
   mocha metal in the waveform needs that ground to be metal at all, and with
   the wave running the full width of its bottom edge.

   ⚠️ THE WAVE IS ABSOLUTE INSIDE THE PANEL, NOT A ROW IN IT. As a row it would
   stop at the panel's padding and read as a chart placed near the bottom. Set
   against the panel's own edges it is CUT by the radius, which is what makes it
   look built into the panel rather than laid on top of it.
   ============================================================ */
/* ⚠️ THE PAGE GROUND BEHIND THE PANEL IS THE SITE'S OWN RAMP — the same four
   stops home runs top to bottom, not a colour picked for this page. It is what
   the panel floats ON, so the two are doing different jobs: the ramp is the
   page, the panel is the object. */
.vwrap { position: relative;
  background: linear-gradient(180deg, #FFFFFF 0%, #FCF9F6 30%, #F1E4D8 62%, #DECBB6 100%);
  padding: 0; }

/* ⚠️ NOT FLOATING. Founder-directed: "dont make voice ai hero floating". It was
   an inset, rounded, shadowed panel; it is now a full-bleed section, edge to
   edge, with no radius and no lift. What survives from that version is the
   part that was never about floating: the ground is `--paper-warm` (#FFFEFC —
   the lightest white on this site, the one with the warm tint), the wave runs
   the full width of the bottom, and the height is home's 950px.

   The ramp stays on `.vwrap` and is now visible only behind the built-using
   strip below, which is where it belongs: the strip is on the page, the hero
   is the page's own surface.

   ⚠️ THE SHADOW HAD TO GO WITH THE FLOAT, and that fixed something too. It fell
   on the paper where the breadcrumb sits and tinted it from #F6F7F8 to
   #ECECF0, which is what took the crumb's grey under 4.5. The crumb keeps its
   darker value regardless — a colour with no margin is a bug waiting for the
   next surface — but the tint itself is gone.

   ⚠️ THE GROUND IS THE SITE'S OWN RAMP. Founder-directed. It was `--paper-warm`
   flat, with the ramp on `.vwrap` behind it doing nothing visible now the hero
   covers the full width. The ramp is the page's gradient everywhere else, and
   its mocha end at the bottom is what the wave's upper half now stands on —
   which is why that half is the lightest white rather than the accent. */
.vhz { position: relative; overflow: hidden; isolation: isolate;
  min-height: 950px;                 /* the home hero's height, founder-directed */
  display: flex; flex-direction: column; justify-content: center;
  background: linear-gradient(180deg,
    #FFFFFF 0%, #FCF9F6 30%, #F1E4D8 62%, #DECBB6 100%); }

@media (max-width: 700px) { .vhz { min-height: 0; padding-block: 96px var(--s5); } }

/* ⚠️ THE COPY IS CENTRED, AND THE PANEL IS WHAT FRAMES IT. An earlier version
   ran the headline across a full-bleed page and still left a third of the
   screen empty — the type was being asked to do the framing on its own. Inside
   a panel the measure IS the composition. */
.vhz__in { position: relative; z-index: 2; width: 100%; max-width: 1100px;
  /* ⚠️ THE BOTTOM PADDING IS THE WAVE'S HEIGHT, and it has to be. The wave is
     absolutely positioned, so it is out of flow and the panel's `justify-
     content: center` centres the copy as though the bottom third of the panel
     were empty — which put the tallest bars straight through "Book a call".
     Reserving the same clamp here is what keeps the copy centred in the space
     that is actually free. Two places holding one number is a drift risk, so
     they are written identically and named to each other. */
  /* ⚠️ CENTRED IN THE PANEL. NOT centred in "the panel minus the wave".
     Founder-directed: "literally center the things regardless of overlapping
     waveform".

     Every position problem this block has had came from the padding that used
     to be here. It reserved the wave's height at the bottom so the copy would
     clear it, which turned a simple centring into arithmetic — and arithmetic
     that changed meaning every time the block's contents changed. Adding the
     actions back, taking them away, shortening the lede: each one moved the
     copy, in the direction opposite to the intuition, because a box centred on
     a fixed axis grows and shrinks around that axis rather than from its top.
     Three separate corrections came out of one padding value.

     With no padding there is no arithmetic. The box is centred in the 950px
     panel, full stop, and it stays centred whatever goes in it. The wave is
     absolutely positioned and out of flow, so if the two meet, they meet —
     which is the instruction. */
  margin-inline: auto; text-align: center;
  padding-inline: var(--gutter); }
.vhz h1 { font-family: var(--display); font-weight: var(--w-display);
  /* ⚠️ ONE LINE ON A DESKTOP, AND THE MEASUREMENTS SAY IT HAS TO BE. The
     headline was breaking as "Miss the call, lose / the customer.", splitting a
     clause. Forcing the break onto the comma is IMPOSSIBLE at 66px: measured,
     "Miss the call, lose" is 569px and "lose the customer." is 588px, so any
     cap narrow enough to break the first line is also too narrow for the
     second, and it breaks twice instead of once. `text-wrap: balance` was tried
     and did not move it at any width from 320 to 1600 — a browser is free to
     decline to balance, so it is not a control.
     58px puts the whole sentence on one line inside the 940px measure. Below
     about 1000px the clamp scales it down and it wraps on its own — at the
     comma, because by then "lose the customer." does fit a line. The right
     break at both ends, from one number. */
  font-size: clamp(29px, 4.3vw, 58px); line-height: 1.03; letter-spacing: -0.028em;
  color: var(--ink); margin-inline: auto; max-width: none; }
/* ⚠️ THE SECOND CLAUSE IS A BLOCK ON A PHONE, AND ONLY THERE. Below ~430 the
   sentence cannot break well at any size: measured, "Miss the call, lose" is
   always narrower than "lose the customer.", so every cap that breaks the
   first line also breaks the second, and it wraps twice. Font-size cannot fix
   it either — one line at 320 would need about 22px. So the break is stated:
   the clause becomes a block, which puts it on the comma. Desktop keeps it
   inline and on one line, where it fits. */
.vhz h1 .cl { display: inline; }
@media (max-width: 700px) { .vhz h1 .cl { display: block; } }
/* ⚠️ NOT `--ink-3`. The hero used to be flat `--paper-warm`, where #6B6B6B is
   fine; it is now the site ramp, and by the lede's position the ground has
   warmed to about #F4E8E0 — which takes that grey to 4.43, under 4.5. Same
   failure as the crumb under the old panel shadow and the strip label on the
   ramp's mocha end: a grey solved against one surface, reused on another.
   #4E4E4E is the value this site already uses for its warmest grounds, so
   there is one answer rather than a third. */
/* ⚠️ TIGHTER, AND THE MEASURE IS PART OF IT. Founder: "improve layout, its all
   spread out". Three things were doing it: 32px above the lede and 48px above
   the actions, which on a 950px panel read as three separate objects rather
   than one block; a 1.55 line-height holding the lede's own two lines apart;
   and a 46ch lede under a ~1000px headline, so the block narrowed by half from
   one element to the next. 24/32, 1.4, and a wider measure make it one shape. */
.vhz__lede { margin: var(--s3) auto 0; max-width: 66ch; font-size: var(--t-md);
  line-height: 1.55; color: #4E4E4E; }
/* ⚠️ THE BREAK IS STATED, NOT BALANCED. Founder: "make the description in a v
   shape from side so br from books or jobs". `text-wrap: balance` does the
   OPPOSITE of what is wanted here — it equalises the two lines (47/56), and a
   V needs the first line long and the second short. So the break is a `<br>`
   after "the job", giving 60/33.

   ⚠️ AND IT IS HIDDEN ON A PHONE. A hard break is right at one width and wrong
   at every other: below 901 the lede wraps to three lines on its own, and a
   `<br>` in the middle of that produces a break nobody chose. `display: none`
   removes it — a `<br>` breaks whatever its display is, EXCEPT `none`, which is
   the one property that switches it off. The space before it survives, so the
   sentence closes up correctly when it is gone. */
.vhz__lede .lb { display: none; }
@media (min-width: 901px) { .vhz__lede .lb { display: inline; } }
/* ⚠️ BALANCE TAKES OVER EXACTLY WHERE THE `<br>` STOPS. With the break hidden
   and a 66ch measure, 900 and 768 orphaned the last word — "…on the / phone."
   The two rules are complements: above 901 the break is chosen and balance
   would fight it; below, nothing is chosen and balance is the only thing
   stopping a one-word line. Same property, opposite jobs, split on the same
   breakpoint so neither can apply where the other is in charge. */
@media (max-width: 900px) { .vhz__lede { max-width: 48ch; text-wrap: balance; } }
.vhz__acts { display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: var(--s4); margin-top: var(--s4); }
/* ⚠️ THESE TWO RULES ARE NOT DEAD, THEY ARE JUST NOT ON THE LIVE HERO ANY MORE.
   The actions came out of /voice-ai/ founder-directed; /vcopy.html still
   renders them in all ten layouts, so deleting the rules would break the picker
   silently. They go when the picker does.
   The number lives in the secondary action rather than as a separate readout:
   one place on the panel, and nothing that can collide with the wave below.
   ⚠️ `gap`, BECAUSE `inline-flex` EATS THE SPACES — a flex container drops
   whitespace-only text nodes between its items, so "Ring it yourself — 07700
   162008 ↗" rendered with both spaces gone. It has to be flex to centre inside
   a 44px target, so the gap puts the spacing back as layout. */
.vhz__ring { font-size: var(--t-sm); font-weight: 600; color: var(--ink);
  display: inline-flex; align-items: center; gap: 0.35em; min-height: 44px;
  border-bottom: 1px solid var(--line-2); }
.vhz__ring b { font-variant-numeric: tabular-nums; font-weight: 600; }
.vhz__ring:hover { color: var(--accent-ink); border-bottom-color: var(--accent-ink); }

/* ⚠️ THE CRUMB HAS TO CLEAR THE WAVE'S LOWER HALF. The divider hangs ~95px
   below the seam and the breadcrumb is the first thing after the hero, so with
   its normal 48px it sat inside the bars. The wave is `pointer-events: none`
   so the links stayed clickable — which is worse, not better: an overlap that
   still works is one nobody notices until a screenshot.
   Scoped to the row that directly follows this page's hero, so no other page's
   crumb moves. */
.vwrap + .crumb-row { padding-top: 150px; }

/* ---- THE WAVEFORM — A RECORDING SCROLLING PAST -------------------------
   ⚠️ THE WAVEFORM IS FIXED AND THE TIME AXIS MOVES UNDER IT. Founder-picked
   option 06 from /wave.html. Four earlier versions animated each bar's HEIGHT
   in place and each needed a fresh correction — grouped by turn, then a jitter
   layer, then a floored envelope, then a raised word-gap floor. Every fix was
   real and every one revealed the next, because the model was wrong: a
   recording does not breathe, it scrolls.

   What that drops: the pulse, the envelope, the per-sample jitter, the bars
   that visibly failed to grow, and about three hundred animations. What is left
   is ONE transform on ONE element.

   ⚠️ IT STILL SITS ON THE SEAM, half above the line and half below, because
   that is what makes it the join between two sections rather than decoration at
   the bottom of one. It is a child of `.vwrap`, not `.vhz` — the hero clips its
   overflow and would eat the lower half.
   ------------------------------------------------------------------------ */
.mw { position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  transform: translateY(50%);
  --wave-h: clamp(120px, 21vh, 240px);
  height: var(--wave-h); overflow: hidden; pointer-events: none; }

/* ⚠️ -50% IS THE ONLY VALUE THAT LOOPS. The strip holds the same samples twice,
   so half its width is exactly one copy — it lands on the start of the second,
   identical to where it began. A percentage, not a pixel figure: the strip's
   width changes with the viewport and the two must always agree.

   ⚠️ AND THE PITCH IS `margin-right` ON THE BAR, NOT `gap` ON THE ROW. With
   `gap`, n bars have n−1 gaps — the two copies are separated by ONE gap and
   half the strip falls a half-gap short of a whole copy, so the loop ticks
   1.5px every cycle. Invisible in a screenshot, visible in motion. As a margin
   both copies are exactly n × (width + gap). */
.mw__s { display: flex; align-items: center; height: 100%; width: max-content;
  animation: roll 46s linear infinite; }
@keyframes roll { to { transform: translateX(-50%); } }
.mw i { flex: 0 0 auto; width: 10px; margin-right: 3px;
  height: calc(var(--h) * 100%); background: var(--ink); }

/* the playhead. ⚠️ ON THE WINDOW, NOT ON THE STRIP — on the strip it would
   scroll along with the samples, which is the opposite of what a playhead is.
   It is what says the audio is moving PAST a point rather than the wave
   wandering on its own. */
.mw::after { content: ''; position: absolute; left: 50%; top: 0; bottom: 0;
  width: 1px; background: var(--ink); opacity: 0.3; }

/* ⚠️ IT STOPS COMPLETELY UNDER REDUCED MOTION, and this setting matters more
   here than it did for the in-place version: a scrolling divider is horizontal
   movement in the reader's periphery, which is the kind that causes trouble.
   What is left is still the right object — a fixed waveform on the seam. */
@media (prefers-reduced-motion: reduce) { .mw__s { animation: none; } }

/* ============================================================
   THE PAGE'S BODY GRAMMAR — A RAIL AND A COLUMN.

   ⚠️ THE PROBLEM IT SOLVES IS A DEAD COLUMN AND A LOST ARGUMENT. Stacked full
   width, every section put its heading and lede in the left ~55ch and left
   roughly 400px of nothing beside them, then dropped the evidence underneath.
   So the reader scrolled PAST the claim to reach the proof, and by the time the
   transcript was on screen the sentence explaining it was not. The page ran
   7,983px doing that.

   Side by side, the claim stays visible while the proof is read, and the width
   that was empty is the width the proof needed. The rail is STICKY for the same
   reason: section 01 is 1,972px of transcript and the heading belongs with all
   of it, not with its first screen.

   ⚠️ ONE GRAMMAR FOR EVERY SECTION, not a layout per section. A page where each
   block finds its own arrangement reads as five pages; the discipline is that
   the rail is always the argument and the column is always the evidence, and
   only the evidence changes shape.

   ⚠️ IT COLLAPSES BELOW 1000. Two columns need a real measure each — a 300px
   rail beside a 300px column is two things too narrow to read rather than one
   good one. Below that it is the stack it always was, which is correct on a
   phone and was never the problem there.
   ============================================================ */
.vsec__g { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: var(--s7); align-items: start; }
@media (max-width: 1000px) { .vsec__g { grid-template-columns: 1fr; gap: var(--s5); } }

.vsec__rail { position: sticky; top: var(--s5); }
@media (max-width: 1000px) { .vsec__rail { position: static; } }
/* the heading steps down from the hero's 58px: it is a section, not the page */
.vsec__rail h2 { font-size: clamp(28px, 2.6vw, 38px); line-height: 1.08;
  letter-spacing: -0.026em; max-width: none; }
.vsec__rail .lede { margin-top: var(--s3); font-size: var(--t-sm); line-height: 1.55;
  color: #4E4E4E; max-width: none; }
/* ⚠️ THE INLINE `style` ATTRIBUTES ON THESE HEADINGS ARE OVERRIDDEN, not
   removed from the markup. They set `max-width` in ch for the full-width
   layout — 20ch inside a 340px rail wraps to five lines. `max-width: none`
   here wins because an inline style loses to `!important` only, and these are
   not important; the rail's own width is doing the constraining now.
   They stay in the source because the same page is the picker's input. */
.vsec__rail h2[style], .vsec__rail .lede[style] { max-width: none !important; }

/* ---- THE FRAME ---------------------------------------------------------
   A card, because a call is a discrete object with a beginning and an end. On
   `--paper` this needs a real edge: the same 1px line plus the shallow lift
   the site's other white surfaces use, so it reads as one of them. */
.call {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xl); overflow: hidden;
  box-shadow: 0 1px 2px rgba(15, 15, 15, 0.04), 0 24px 60px -40px rgba(15, 15, 15, 0.28);
}

.call__h {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: var(--s3) var(--s5); border-bottom: 1px solid var(--line);
}
.call__hl { font-family: var(--mono); font-size: 11px; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3); }
.call__hr { font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  color: var(--ink-4); font-variant-numeric: tabular-nums; white-space: nowrap; }

.call__b { padding: var(--s5) var(--s5) var(--s4); }

/* ---- A ROW -------------------------------------------------------------
   Two columns: the elapsed clock, then everything else. The clock is a fixed
   track and `tabular-nums`, so 00:07 and 00:41 occupy the same width and the
   words start on one edge all the way down — a ragged left margin down a
   transcript reads as damage. */
.call__r { display: grid; grid-template-columns: 58px minmax(0, 1fr); gap: var(--s3);
  padding: 11px 0; }
.call__r + .call__r { border-top: 1px solid var(--line); }
.call__t { font-family: var(--mono); font-size: 11px; color: var(--ink-4);
  font-variant-numeric: tabular-nums; padding-top: 4px; }

.call__who { font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-4); }
/* ⚠️ BRAND ON THE SYSTEM'S NAME ONLY. Green is a signal on this site and never
   a fill — it marks the thing that is us, in a transcript where the other
   voice is the customer. Two ink greys would make the reader work out who is
   speaking on every row. */
.call__r--it .call__who { color: var(--brand); }
.call__w { font-size: var(--t-md); line-height: 1.45; color: var(--ink);
  margin-top: 6px; max-width: 56ch; }
.call__r--them .call__w { color: var(--ink-2); }

/* ---- WHAT IT DID, MID-SENTENCE ----------------------------------------
   Not a row of its own: it belongs to the line above it, so it is indented
   into the words column and marked rather than bordered. Mono because it is
   machine output and should not be mistaken for something anybody said. */
.call__do { display: flex; align-items: flex-start; gap: 10px; margin-top: 10px;
  font-family: var(--mono); font-size: 11px; line-height: 1.5; color: var(--ink-3);
  letter-spacing: 0.01em; }
.call__do::before { content: ''; flex: 0 0 auto; width: 5px; height: 5px; margin-top: 6px;
  border-radius: 50%; background: var(--brand); }
.call__do b { color: var(--ink-2); font-weight: 500; }

/* the two bare rows — the ring at the start and the hang-up at the end. They
   are events, not speech, so they carry no speaker and no bubble. */
.call__r--ev .call__w { font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-4); margin-top: 0; padding-top: 3px; }

/* ---- THE OUTCOME ------------------------------------------------------
   The point of the whole artefact, so it is the last thing and it is stated
   flatly. Chips rather than a sentence: four facts that can each be checked
   against the transcript above them. */
.call__f { display: flex; flex-wrap: wrap; gap: 8px;
  padding: var(--s3) var(--s5) var(--s4); border-top: 1px solid var(--line); }
.call__c { font-family: var(--mono); font-size: 11px; letter-spacing: 0.04em;
  color: var(--ink-2); background: var(--white); border: 1px solid var(--line-2);
  border-radius: var(--r-pill); padding: 6px 12px; white-space: nowrap; }
.call__c--y { border-color: color-mix(in srgb, var(--brand) 40%, var(--line-2));
  color: var(--brand-ink, var(--ink)); }
.call__c--y::before { content: ''; display: inline-block; width: 5px; height: 5px;
  border-radius: 50%; background: var(--brand); margin-right: 8px; vertical-align: 1.5px; }

/* ---- THE SIDE NOTE ----------------------------------------------------
   One line under the artefact saying what is invented and what is not. It is
   small and it is not optional: the transcript is a composite, and a page that
   shows a specific call without saying so is claiming a case study it has not
   earned. → the same discipline as home's "no trade customer is live yet". */
.call__n { font-size: var(--t-sm); line-height: 1.6; color: var(--ink-4);
  margin-top: var(--s3); max-width: 62ch; }
/* the number in this note is the same offer as the one in the page head, so it
   has to be tappable there too — it rendered at its 19px line box. Padding,
   never font-size: SC 2.5.8 asks 24, a thumb wants 44. */
.call__n a { color: var(--ink-2); font-weight: 600; border-bottom: 1px solid var(--line-2);
  display: inline-flex; align-items: center; min-height: 24px; }
.call__n a:hover { color: var(--ink); border-bottom-color: var(--ink); }
@media (pointer: coarse) { .call__n a { min-height: 44px; } }

/* ---- THE PAIRED LISTS -------------------------------------------------
   Section 04 is two lists that only mean something beside each other: when it
   hands over, and what it will not do. Side by side on a desktop because the
   pairing IS the argument; stacked below 900 where two 3-item columns would
   each be too narrow to read.  */
.pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
@media (max-width: 900px) { .pair { grid-template-columns: 1fr; gap: var(--s5); } }
.pair__h { display: flex; align-items: baseline; gap: 12px; padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line-2); }
.pair__t { font-family: var(--display); font-weight: var(--w-display); font-size: var(--t-lg);
  letter-spacing: -0.028em; line-height: 1.1; color: var(--ink); }
.pair__i { padding-top: var(--s3); }
.pair__i + .pair__i { border-top: 1px solid var(--line); margin-top: var(--s3); }
.pair__n { font-size: var(--t-body); font-weight: 600; color: var(--ink);
  font-family: var(--display); letter-spacing: -0.015em; line-height: 1.25; }
.pair__d { font-size: var(--t-sm); line-height: 1.55; color: var(--ink-3); margin-top: 6px; }

/* ---- PHONE ------------------------------------------------------------
   The desktop composition is the designed one. This is the honest reflow, not
   a second design: the clock moves above the words rather than being squeezed
   into a 58px track beside a 30ch line. */
@media (max-width: 720px) {
  .call__h, .call__f { padding-inline: var(--s4); }
  .call__b { padding: var(--s4) var(--s4) var(--s3); }
  .call__r { grid-template-columns: 1fr; gap: 4px; }
  .call__t { padding-top: 0; }
  .call__w { font-size: var(--t-body); }
}
