/* ============================================================
   LEVRG v3 — COMPONENTS + SECTIONS
   Each block names the reference it came from.
   ============================================================ */

/* ---- 1. DOTTED FIELD  (Attio) -------------------------------
   A faint dot grid behind the hero. Attio's is the model: it is not
   decoration, it registers the page to a measure, and it fades out
   so it never competes with the type sitting on it. */
.field { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.field::before {
  content: ''; position: absolute; inset: 0;
  background-image: radial-gradient(var(--line-2) 1px, transparent 1px);
  background-size: 26px 26px;
  mask-image: radial-gradient(90% 70% at 50% 22%, #000 0%, transparent 76%);
  -webkit-mask-image: radial-gradient(90% 70% at 50% 22%, #000 0%, transparent 76%);
  opacity: 0.7;
}

/* ---- 2. NAV ------------------------------------------------- */
.nav { display: flex; align-items: center; gap: var(--s3); padding-block: var(--s3); }
.nav__brand {
  width: 84px; height: 24px; background: var(--ink);
  -webkit-mask: url('../logos/levrg-wordmark.png') no-repeat center/contain;
  mask: url('../logos/levrg-wordmark.png') no-repeat center/contain;
}
.nav__links { display: flex; gap: var(--s4); margin-left: var(--s5); }
.nav__link { font-size: var(--t-sm); color: var(--ink-3); transition: color var(--fast) var(--ease); }
.nav__link:hover { color: var(--ink); }
.nav__spacer { flex: 1; }
@media (max-width: 860px) { .nav__links { display: none; } }

/* ---- 3. BUTTONS --------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--sans); font-size: var(--t-sm); font-weight: 600; letter-spacing: -0.005em;
  padding: 13px 22px; border-radius: var(--r-btn); border: 1px solid transparent; cursor: pointer;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.btn--brand { background: var(--ink); color: var(--white); }
.btn--brand:hover { background: #2A2A2A; }   /* lifts, not greens — green stays a signal */
.btn--ghost { background: var(--white); color: var(--ink); border-color: var(--line-2); box-shadow: var(--lift-1); }
.btn--ghost:hover { border-color: var(--ink-4); }
.btn--sm { padding: 9px 16px; font-size: var(--t-xs); }
.btn--lg { padding: 16px 28px; font-size: var(--t-body); }

/* ---- 4. BADGE  (Attio / Symbolic) ---------------------------
   A pill above the headline that says what category this is. Both
   references use it; it does the job an eyebrow caption used to do
   without being a small-uppercase-mono eyebrow. */
.badge {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px; border-radius: var(--r-pill);
  border: 1px solid var(--brand-line); background: var(--brand-wash);
  font-size: var(--t-xs); font-weight: 600; color: var(--brand);
}
.badge__dot { width: 6px; height: 6px; border-radius: var(--r-pill); background: var(--brand-hot); }
.badge__dot--live { animation: ping 2.4s var(--ease) infinite; }
@keyframes ping {
  0%   { box-shadow: 0 0 0 0 rgba(0,168,85,0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(0,168,85,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,168,85,0); }
}
@media (prefers-reduced-motion: reduce) { .badge__dot--live { animation: none; } }

/* ---- 5. TAG ROW  (Midday) -----------------------------------
   A row of pills under the actions carrying the four things people
   actually want to know, in four words each. Cheaper than a feature
   grid and it sits in the hero's dead space. */
.tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--s4); }
.tag {
  padding: 8px 14px; border: 1px solid var(--line); border-radius: var(--r);
  background: var(--white); font-size: var(--t-xs); color: var(--ink-2);
}

/* ---- 6. SCATTER  (Amplemarket) ------------------------------
   Amplemarket rings its headline with small tinted cards, each
   carrying one real figure. It turns proof into texture — the page
   feels populated without a paragraph of claims. Ours carry real
   call outcomes. Absolute on desktop, a plain row on mobile, and
   never overlapping the text column. */
.scatter { position: absolute; inset: 0; pointer-events: none; }
.chip {
  position: absolute; display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: var(--r-lg);
  box-shadow: var(--lift-2); font-size: var(--t-xs); font-weight: 600; color: var(--ink);
  white-space: nowrap;
}
.chip__k { font-family: var(--mono); font-size: 10px; color: var(--ink-2); letter-spacing: 0.04em; }
.chip--1 { background: var(--tint-1); top: 12%;  left: 2%; }
.chip--2 { background: var(--tint-2); top: 30%;  left: -1%; }
.chip--3 { background: var(--tint-3); top: 58%;  left: 4%; }
.chip--4 { background: var(--tint-4); top: 16%;  right: 1%; }
.chip--5 { background: var(--tint-5); color: #fff; top: 40%; right: -2%; }
.chip--5 .chip__k { color: rgba(255,255,255,0.62); }
.chip--6 { background: var(--brand-hot); color: var(--ink); top: 63%; right: 3%; }
.chip--6 .chip__k { color: rgba(16,18,17,0.55); }
@media (max-width: 1180px) { .scatter { display: none; } }

/* ---- 7. PANEL — the product, floating  (Attio) --------------- */
.panel {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--lift-4); overflow: hidden;
}
.panel__bar {
  display: flex; align-items: center; gap: var(--s2);
  padding: 14px var(--s3); border-bottom: 1px solid var(--line);
}
.panel__title { font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
.panel__meta { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--ink-4); font-variant-numeric: tabular-nums; }
.row {
  display: grid; grid-template-columns: 30px 1fr auto auto; gap: var(--s3);
  align-items: center; padding: 13px var(--s3); border-bottom: 1px solid var(--line);
  transition: background var(--fast) var(--ease);
}
.row:last-child { border-bottom: 0; }
/* A panel with no durations should not carry an empty duration column —
   four rows of em-dash is a column that exists only because the component
   has one. */
.panel--nodur .row { grid-template-columns: 30px 1fr auto; }
.row:hover { background: #FAFAFA; }
.row__tag {
  width: 30px; height: 30px; display: grid; place-items: center; border-radius: var(--r-pill);
  border: 1px solid var(--line-2); font-family: var(--mono); font-size: 10px; color: var(--ink-3);
}
/* block, not inline — as inline spans these two ran together on one line
   and the row read as a single run-on sentence. */
.row__who { display: block; color: var(--ink); font-weight: 600; font-size: var(--t-sm); line-height: 1.25; }
.row__note { display: block; font-size: var(--t-xs); color: var(--ink-4); margin-top: 2px; line-height: 1.3; }
.row__val { font-family: var(--mono); font-size: var(--t-xs); color: var(--ink); text-align: right; }
.row__st {
  font-size: var(--t-xs); color: var(--ink-3); white-space: nowrap;
  padding: 4px 10px; border: 1px solid var(--line); border-radius: var(--r-pill);
}
.row--live .row__st { color: var(--brand); border-color: var(--brand-line); background: var(--brand-wash); }
.row--flag .row__st { color: var(--alarm-dim); border-color: #F0C9C0; }
.row__t   { font-family: var(--mono); font-size: 11px; color: var(--ink-4); min-width: 34px; text-align: right; }
.row--live .row__tag { border-color: var(--brand-hot); color: var(--brand); background: var(--brand-wash); }
.row--flag { background: var(--alarm-wash); }
.row--flag .row__tag { border-color: var(--alarm); color: var(--alarm-dim); background: transparent; }
/* The flag tint is lighter than white, so greys that clear AA on a white row
   fall short on this one. Text inside a tinted row takes its own step —
   a background that changes must take its foregrounds with it. */
.row--flag .row__note,
.row--flag .row__t { color: #7A5148; }

/* small floating chips ON the panel (Attio's "Meeting in progress") */
.panel-wrap { position: relative; }
.float {
  position: absolute; display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 13px; border-radius: var(--r-pill); background: var(--white);
  border: 1px solid var(--line); box-shadow: var(--lift-3);
  font-size: var(--t-xs); font-weight: 600; color: var(--ink); white-space: nowrap;
}
.float--a { left: -30px; bottom: -18px; }
.float--b { right: -22px; top: -18px; }
@media (max-width: 1040px) { .float { display: none; } }

/* ---- 8. SECTION MARK ---------------------------------------- */
.mark { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s3); }
.mark__n { font-family: var(--mono); font-size: 11px; color: var(--brand); letter-spacing: 0.1em; }
.mark__t { font-family: var(--mono); font-size: 11px; color: var(--ink-4); letter-spacing: 0.1em; text-transform: uppercase; }

/* ---- 9. STATS ----------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px,1fr)); gap: var(--s5); }
.stat__v { font-family: var(--display); font-weight: var(--w-display); font-size: var(--t-lg); letter-spacing: -0.04em; color: var(--ink); line-height: 1; }
.stat__l { font-size: var(--t-xs); color: var(--ink-3); margin-top: 10px; }

/* ---- 10. TRIO ----------------------------------------------- */
.trio { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px,1fr)); gap: var(--s4); }
.card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: var(--s4); box-shadow: var(--lift-1);
}
.card__t { font-family: var(--display); font-weight: var(--w-display); font-size: var(--t-md); letter-spacing: -0.02em; color: var(--ink); margin-top: var(--s3); }
.card__b { font-size: var(--t-sm); line-height: 1.55; color: var(--ink-3); margin-top: 8px; }
.card__mini { border: 1px solid var(--line); border-radius: var(--r); background: var(--white); padding: var(--s2); height: 104px; overflow: hidden; }

/* ---- 11. SPLIT ---------------------------------------------- */
.split { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.15fr); gap: var(--s6); align-items: start; }
@media (max-width: 960px) { .split { grid-template-columns: 1fr; gap: var(--s5); } }

/* ---- 12. QUOTE  (Amplemarket) -------------------------------
   ⚠️ `.quote p` styled BOTH children, because the attribution is a
   <p> too — so the credit rendered at quote size and weight and the
   block read as two quotes. The quote text now carries its own
   class; nothing is styled by element inside here.

   Also un-indented: it used a left border plus padding, which set
   it 26px in from the heading, copy and tags above it. A quote that
   does not share the column's left edge reads as misaligned rather
   than as emphasised. The rule above the credit does the separating. */
.quote { max-width: 40ch; }
.quote__t {
  font-family: var(--display); font-weight: var(--w-display);
  font-size: var(--t-body); line-height: 1.45; letter-spacing: -0.012em; color: var(--ink);
}
.quote__by {
  margin-top: var(--s2); padding-top: var(--s2);
  border-top: 1px solid var(--line);
  font-family: var(--sans); font-weight: 400;
  font-size: var(--t-xs); line-height: 1.5; letter-spacing: 0; color: var(--ink-3);
}
.quote__by strong { color: var(--ink); font-weight: 600; }

/* ---- 13. LEDGER --------------------------------------------- */
/* The comparison sits on a WHITE card now that the page ground is --paper.
   Before this the table floated directly on the page, which was fine on white
   but reads as unfinished on a tint — the rules ran edge to edge with nothing
   holding them. The card is the container; the ink column stays exactly as it
   was, a rounded block floating inside it. */
/* No border either. With the padding gone the ink column meets the card's edge,
   and a 1px --line border becomes a grey hairline drawn around the black block
   — it also made the card exactly 2px taller than the column. The white fill
   plus the shadow already separate the card from the tinted page. */
.ledger-card { background: var(--white); border-radius: var(--r-xl);
  box-shadow: 0 1px 2px rgba(15,15,15,0.04), 0 20px 44px -26px rgba(15,15,15,0.16);
  overflow-x: auto; }
/* NO padding on the card. The card's height must equal the ink column's height,
   and the ink column spans the whole table (its header cell is black too) — so
   any vertical padding makes the white taller than the black by exactly that
   much. The cells carry their own padding, so nothing touches an edge.
   With the padding gone the ink column reaches the card's corners, and the card
   clips them: the column's own radii are removed below so the two agree. */
.ledger { width: 100%; border-collapse: collapse; }
.ledger th, .ledger td { text-align: left; padding: 16px var(--s3); border-bottom: 1px solid var(--line); vertical-align: top; }
.ledger thead th { font-size: var(--t-xs); font-weight: 600; color: var(--ink-4); border-bottom-color: var(--line-2); white-space: nowrap; }
.ledger tbody th { color: var(--ink); font-weight: 600; font-size: var(--t-sm); width: 30%; }
.ledger td { color: var(--ink-3); font-size: var(--t-sm); }
/* INK, not green. The live-line panel was changed first and this column was
   missed — two solid green blocks on a white page is the "green container"
   again, just in a second place. Green is a SIGNAL on this page: the live dot,
   the section numbers, the phone number. It never fills a container. */
.ledger tbody tr:last-child th, .ledger tbody tr:last-child td { border-bottom: 0; }
.ledger .ours { background: var(--ink); color: var(--white); border-bottom-color: rgba(255,255,255,0.12); }
.ledger thead th.ours { color: var(--white); border-bottom-color: rgba(255,255,255,0.26); }
.ledger tbody tr:last-child .ours { border-bottom-color: var(--ink); }

/* ---- 14. THE LIVE LINE PANEL -------------------------------
   Was a full-bleed green block. Founder-directed: the green
   container goes. It is INK now — which is also what Notion,
   Relume and Vercel do for a closing panel — and green survives
   only where it means something: the live dot and the number
   itself. A colour that fills a container stops being a signal. */
.brandpanel { background: var(--ink); border-radius: var(--r-xl); padding: var(--s7) var(--s6); color: var(--white); position: relative; overflow: hidden; }
.brandpanel h2 { color: var(--white); }
.brandpanel .lede { color: rgba(255,255,255,0.78); }
.dial {
  display: inline-block; margin-top: var(--s3);
  font-family: var(--display); font-weight: var(--w-display);
  font-size: clamp(34px, 5.4vw, 74px); line-height: 1; letter-spacing: -0.05em; color: #FFFFFF;
  border-bottom: 2px solid rgba(255,255,255,0.32); padding-bottom: 6px;
}
.dial:hover { border-bottom-color: #FFFFFF; }
/* The hero's gradient, in its dark register — pulled to the TOP RIGHT and
   brighter. Same three hues in the same order (green, blue, yellow), so the
   top and bottom of the page read as one light source.

   Authored for ink, not copied: on white the hero runs alphas of
   0.34/0.22/0.20; those wash out to grey over #0F0F0F, so they go up and each
   hue is pushed a step brighter. A gradient has to be authored for the ground
   it sits on. */
.brandpanel__glow {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(closest-side, rgba(0,225,112,0.62), transparent 72%) 58% -14%/58% 120% no-repeat,
    radial-gradient(closest-side, rgba(70,155,255,0.52), transparent 72%) 84% -22%/56% 120% no-repeat,
    radial-gradient(closest-side, rgba(255,205,80,0.46), transparent 72%) 108% 6%/54% 120% no-repeat;
  filter: blur(4px);
  /* fades away from the corner it comes from, so the copy at lower-left sits
     on clean ink and the source reads as off-frame */
  mask-image: radial-gradient(120% 105% at 88% -6%, #000 0%, rgba(0,0,0,0.55) 46%, transparent 82%);
  -webkit-mask-image: radial-gradient(120% 105% at 88% -6%, #000 0%, rgba(0,0,0,0.55) 46%, transparent 82%);
}

/* ---- 15. FOOTER --------------------------------------------- */
/* ⚠️ THE RULE ABOVE THE FOOTER IS CONDITIONAL, AND THE CONDITION IS WHAT IT IS
   FOR. Founder: "there is a divider in footer that we dont need on this page
   cause we dont have that fifteen minutes section like home".

   It exists to separate the close from the footer nav WHEN BOTH SIT ON THE SAME
   DARK GROUND — home's fifteen-minutes close is `.sec--ink`, so without a line
   the two blocks run together on one black field. On a page whose close is
   light, the slab's own top edge is already a hard colour change, and a
   hairline 64px inside it is a second divider separating nothing.

   So it keys off the previous sibling rather than off the page. Every page that
   ends on an ink section keeps it, every page that does not loses it, and a
   page built next week gets the right answer without anyone remembering this. */
.foot { padding-block: var(--s6); display: grid; grid-template-columns: 1.5fr repeat(3,1fr); gap: var(--s5); }
.sec--ink + .foot-slab .foot { border-top: 1px solid var(--line); }
@media (max-width: 820px) {
  .foot { grid-template-columns: 1fr 1fr; }
  /* ⚠️ THE BRAND COLUMN SPANS BOTH. It is the only cell holding a PARAGRAPH; the
     other three are link lists, which are happy in half a column. At two columns
     the tagline had a 151px measure and ran to twelve lines and 264px — taller
     than the three link columns beside it put together. A running sentence and a
     stack of links do not want the same width. */
  .foot__col:first-child { grid-column: 1 / -1; }
}
.foot__col { display: flex; flex-direction: column; gap: 10px; }
.foot__h { font-size: var(--t-xs); font-weight: 600; color: var(--ink); margin-bottom: 4px; }
.foot a { font-size: var(--t-sm); color: var(--ink-3); }
.foot a:hover { color: var(--ink); }

/* ---- 16. REVEAL ---------------------------------------------
   ⚠️ THE HIDDEN STATE IS GATED ON .js, ON PURPOSE.
   Written the obvious way — `[data-rise] { opacity: 0 }` in the
   stylesheet — content is invisible by default and only JS can
   bring it back. Anything that stops the observer firing (a fast
   scroll, an anchor jump into mid-page, a script error, JS off)
   leaves whole sections permanently blank. That is exactly what
   happened here: ten elements never received the class and the
   page rendered mostly empty.

   So the hidden state only exists once JS has proven it is running
   AND is paired with a hard timeout in site.js that reveals
   anything still hidden. Reveal is decoration; it is never the
   thing standing between a visitor and the content. */
.js [data-rise] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.js [data-rise].in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-rise] { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   MARQUEE — a white band under the hero.

   The page ground is now --paper (#F6F7F8), so this reads as a
   white strip laid ON the page rather than as a tinted band cut
   into it. That inversion is the whole point: it is the only pure
   white full-width surface above the fold.

   MECHANICS, and the one that always bites: spacing between items
   is `margin-inline-end`, never `gap`. The track is duplicated and
   translated -50%, and n items joined by `gap` give 2n-1 gaps
   across two copies, not 2n — so the loop lands short and visibly
   jumps once per cycle. Margin belongs to the item, so it repeats
   with it.
   ============================================================ */
.mq { background: var(--white); border-block: 1px solid var(--line);
  overflow: hidden; position: relative; }
.mq__vp { display: flex; width: max-content;
  animation: mq 42s linear infinite;
  /* fade both ends so items enter and leave rather than pop */
  }
.mq:hover .mq__vp { animation-play-state: paused; }
.mq__t { display: flex; align-items: center; padding-block: 20px; }
.mq__i { display: inline-flex; align-items: center; gap: 12px; margin-inline-end: 56px;
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.mq__i::before { content: ''; width: 6px; height: 6px; border-radius: 99px;
  background: var(--brand-hot); flex: 0 0 auto; }
/* The label is OPAQUE for its whole width, with the fade pushed OUTSIDE its
   right edge. A gradient that starts going transparent inside the label's own
   box lets items show through it mid-word — "EVERY CALL promises" — which
   reads as broken text rather than as something passing behind. */
.mq__lab { position: absolute; left: 0; top: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; padding-inline: max(24px, calc(50vw - 600px)) var(--s4);
  background: var(--white);
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--ink-4); }
/* 150px, not 64. A short fade chops a word mid-letter as it emerges — it reads
   as clipped text, not as something dissolving. The fade needs to be longer
   than a word for the effect to be legible as a fade at all. */
.mq__lab::after { content: ''; position: absolute; left: 100%; top: 0; bottom: 0; width: 150px;
  background: linear-gradient(90deg, var(--white) 8%, transparent); }
.mq::after { content: ''; position: absolute; inset: 0 0 0 auto; width: 150px; z-index: 2;
  background: linear-gradient(90deg, transparent, var(--white)); pointer-events: none; }
@keyframes mq { from { transform: translate3d(0,0,0) } to { transform: translate3d(-50%,0,0) } }
@media (prefers-reduced-motion: reduce) { .mq__vp { animation: none; } }
@media (max-width: 700px) { .mq__lab { display: none; } }


/* ---- THE LOGO WALL — `.mq--logos` --------------------------
   ⚠️ IT MUST STAY ABOVE `.mq--edge`, AND THAT IS LOAD-BEARING.
   `.mq--logos .mq__i::before` (display: none — kill the green dot) and
   `.mq--edge .mq__i::before` (display: block — the mark IS the ::before) are
   both (0,2,1). Nothing but source order separates them, and the band uses
   BOTH classes. When these two blocks were moved here from `home.css` and
   `s02hand.css` they were appended in the order they were read, which put
   `--logos` last and blanked every logo on both bands — the strip rendered as
   an empty gradient with a label on it. Their original files happened to load
   in the right order; inside one file the order has to be stated. */
.mq--logos .mq__i { margin-inline-end: 72px; }
.mq--logos .mq__i::before { display: none; }
.mq__logo { height: 22px; width: auto; display: block;
  filter: grayscale(1); opacity: 0.46; }
@media (max-width: 700px) { .mq--logos .mq__i { margin-inline-end: 48px; } }

/* ============================================================
   THE BAND AT A SECTION'S BOTTOM EDGE — `.mq--edge`.

   ⚠️ AUTHORED FOR HOME SECTION 02, NOW ALSO THE VOICE AI PIPELINE'S BOTTOM
   EDGE. Moved here from `s02hand.css` and `home.css` the moment it had a second
   caller: it MODIFIES `.mq`, so it belongs beside it, and the alternative was
   copying sixty lines of hard-won CSS into a page stylesheet and letting the
   two bands drift. It must stay AFTER the `.mq` block above — `.mq--edge` and
   `.mq` are both (0,1,0), so order is the only thing that decides. */
/* ⚠️ A FLEX ROW: the fixed label, then the scrolling viewport. The band used to
   be the scroller itself; splitting it is what lets a label be fixed here at
   all, because beside the track it needs no fill and nothing passes under it.
   The left padding puts the label on the page's text column rather than on the
   raw viewport edge, so it lines up with the heading above it. */
.mq--edge {
  margin-top: var(--s7);
  display: flex; align-items: center; gap: var(--s4);
  /* ⚠️ THE BAND'S OWN GUTTER, not the text column's. Founder: "make Built using
     more left". It was `max(--gutter, 50vw - --max/2)`, which lines the label up
     with the 1200px column the headings sit in — 120px at 1440. But the band is
     full-bleed: it is the section's bottom EDGE, not a row inside the column, so
     its label belongs on the band's own edge padding. 56px at 1440, and
     unchanged at 20px on a phone, where the two expressions already agreed. */
  padding-left: var(--gutter);
  background: linear-gradient(90deg,
    #FFFFFF 0%, #FCF9F6 30%, #F1E4D8 62%, #DECBB6 100%);
  border-block: 0; border-top: 1px solid rgba(15,15,15,0.10); }
/* ⚠️ THE FADE MOVED FROM THE BAND TO THE VIEWPORT. On the band it faded the
   first 7% to transparent — which is exactly where the label now sits, so the
   thing that exists to soften logos entering would have faded out the label
   instead. It belongs to the scroller, not to the surface. */
.mq--edge .mq__clip {
  flex: 1; min-width: 0; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 92%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 92%, transparent 100%); }
/* the painted label and fades are the things being replaced — they would sit on
   top of the mask as opaque rectangles */
.mq--edge .mq__lab, .mq--edge::before, .mq--edge::after { display: none; }
.mq--edge .mq__t { padding-block: 15px; }

/* THE MARKS ARE STILL MASKS, repainted for a LIGHT band. On the black strip they
   were the mocha wash; on a ramp that runs white to mocha they need a dark ink
   that holds at BOTH ends — #3A312C measures 21:1 on the white end and 8:1 on
   the mocha, where the bronze would have vanished into the right-hand third.
   ⚠️ display / width / height / border-radius all reset: `.mq__i::before` is
   site.css's green bullet, and repurposing it means undoing its geometry. Every
   one of those four cost a separate bug the first time round. */
.mq--edge .mq__i { position: relative; }
.mq--edge .mq__logo { visibility: hidden; }
.mq--edge .mq__i::before {
  display: block; width: auto; height: auto; border-radius: 0;
  content: ''; position: absolute; inset: 0; background: #3A312C;
  -webkit-mask: var(--logo) no-repeat center / contain;
          mask: var(--logo) no-repeat center / contain; }

/* ---- "BUILT USING", INSIDE THE BAND ------------------------
   Founder-directed: the paragraph above the strip is gone and the label rides
   in the track with the marks, at every width.

   ⚠️ IT IS A TRACK ITEM, WHICH IS THE ONLY PLACE IT CAN BE. The band paints a
   90deg gradient of its own AND masks both ends to transparent, so a label
   pinned to the band would need an opaque fill matching the gradient at that x
   to stop logos sliding under it — the exact failure that got a painted label
   deleted from this band twice. In the track it needs no fill: it sits on
   whatever the band is painting at that moment, exactly as the marks do.

   ⚠️ AND IT MUST CANCEL `.mq--edge .mq__i::before`. That rule turns every item
   into a masked block of #3A312C using `var(--logo)`. The label has no
   `--logo`, so the mask resolves to nothing and the ::before paints a SOLID
   RECTANGLE over the words. Same ink as the marks, which is the value already
   solved for this band: #3A312C measures 21:1 on the white end and 8:1 on the
   mocha, so it holds wherever the item happens to be as it travels. */
.mq--edge .mq__built {
  flex: 0 0 auto;
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.11em;
  text-transform: uppercase; color: #3A312C; white-space: nowrap;
}
/* the label sits on the WHITE end of the band's gradient, where #3A312C — the
   ink the marks are painted in — measures 21:1. It is outside the track, so it
   never travels into the mocha end the way an item would. */

/* On a phone the band has ~250px left for the strip once the label and the
   gutter are taken, which still shows a mark and a half in motion. Stacking it
   instead would make the label a caption again, which is the thing that just
   came out. */
@media (max-width: 700px) {
  .mq--edge { gap: var(--s3); }
}



/* Playwright sweep, S143: the nav links measured 20-21px tall against the
   WCAG 2.2 pointer minimum of 24. They are inline text with no padding, so the
   floor is stated rather than inferred from line-height. */
.nav__link, .nav__mi, .navsheet__grid a, .navsheet__row a {
  min-height: 24px; display: inline-flex; align-items: center;
}


/* ============================================================
   SHARED CHROME — THE CLOSE AND THE FOOTER

   ⚠️ MOVED HERE FROM home.css. The <footer> markup is shared by every page
   (`website/v3/_shell/footer.html`), but half its stylesheet lived in the
   home page's, which no other page loads. The first page that did not load
   home.css painted the whole legal row at #3F3F3F on black — 1.99:1,
   invisible — and reported every footer link as an undersized tap target.
   Shared markup needs a shared stylesheet, the same lesson `nav.css` is.
   ============================================================ */
/* ---- CLOSE + FOOTER ----------------------------------------- */
.close { display: grid; grid-template-columns: minmax(0,1.4fr) auto; gap: var(--s6); align-items: center; }
@media (max-width: 860px) { .close { grid-template-columns: 1fr; gap: var(--s4); } }
/* ⚠️ THE CTA COLUMN. This was an inline `style="text-align:right"` in the
   markup, which is correct on the two-column desktop close and wrong the moment
   the grid folds: on a phone the button and its note hung off the right edge of
   a full-width column with the headline left-aligned above them. An inline
   style also cannot be answered by a media query without `!important`, so the
   alignment moved into the stylesheet where the breakpoint already lives. */
.close__act { text-align: right; }
@media (max-width: 860px) {
  .close__act { text-align: left; }
  /* full width, because a 390px screen has room for exactly one primary action
     and a button that stops halfway reads as a secondary one */
  .close__act .btn { display: flex; width: 100%; justify-content: center; }
}

.close__alt { margin-top: var(--s3); font-size: var(--t-sm); color: var(--ink-3); }
/* ⚠️ TWO LINES, NOT A WRAPPED SENTENCE. As running text the phone number and
   the email are separated by a middot, and at 390 the wrap landed AFTER the
   middot — leaving a separator dangling at the end of one line and the email
   alone on the next, each carrying its own underline stub. A separator only
   works while both things it separates are on the same line, so on a phone the
   line becomes a stack and the middot is dropped rather than re-positioned. */
@media (max-width: 700px) {
  .close__alt { display: grid; justify-items: start; gap: 6px; }
  .close__alt span[aria-hidden] { display: none; }
}
.close__alt a { color: var(--ink); font-weight: 600; border-bottom: 1px solid var(--line-2); }
.close__alt a:hover { border-bottom-color: var(--ink); }

.foot__legal {
  border-top: 1px solid var(--line); padding-block: var(--s3) var(--s6);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4);
  font-size: var(--t-xs); color: var(--ink-4);
}
.foot__legal > span:first-child { margin-right: auto; max-width: 68ch; }
/* the five links travel as one block, and keep their own spacing inside it */
.foot__legal-links { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); }
/* .foot a does NOT reach these — .foot__legal is a SIBLING of .foot, not a
   child of it, so the legal links would inherit body colour and read as plain
   text. Styled here rather than by widening the .foot selector, which would
   also catch the wordmark. */
.foot__legal a { color: var(--ink-4); }
.foot__legal a:hover { color: var(--ink); }
/* The last seven undersized targets the sweep found — the two inline links in
   the close paragraph and the five footer legal links. They carry no class of
   their own, which is why the earlier component selectors missed them: I fixed
   `.nav__link` and friends and the count did not move. Selected by their
   CONTAINER instead.
   ⚠️ `inline-flex` would break the ones inside a sentence — an inline-flex link
   mid-paragraph stops sharing the line box and drops to its own line. They get
   padding-block instead, which grows the hit area without leaving the flow. */
.close__alt a { padding-block: 4px; }
.foot__legal a { min-height: 24px; display: inline-flex; align-items: center; }

/* The footer legal links get the TOUCH minimum on a phone. They were fixed to
   24px for pointer, which is correct on desktop and still too small under a
   thumb — the same 24-vs-44 distinction the body links needed. */
@media (max-width: 900px) {
  .foot__legal a { min-height: 44px; }
}

/* ---- TOUCH TARGETS ON THE SHARED CHROME ---------------------
   Moved out of home.css with the rules above. The footer IS the sitemap on this
   site (D-142.3), so its links are real navigation, not boilerplate — and a
   link's line box is 20px, which is fine under a pointer and not under a thumb.
   Padding, never font-size: the type scale is not the problem. */
@media (max-width: 1000px) {
  .foot__col a, .foot__legal a, .close__alt a { display: inline-flex; align-items: center; min-height: 44px; }
  .foot__col { gap: 0; }
  .foot__legal { row-gap: 0; }
  /* ⚠️ 112px OF BLACK AFTER THE LAST LINK. The legal row's own 64px bottom
     padding and the slab's 48px stacked, and nobody was looking at them
     together — the same "sum of three values" that once left 242px between the
     close and the footer. 40 and 32 is still a clear ending without the page
     appearing to have stopped early. */
  .foot__legal { padding-bottom: var(--s5); }
  .foot-slab { padding-block: var(--s5) var(--s4); }
}


/* ============================================================
   THE THREE-STEP STRIP.

   ⚠️ MOVED HERE FROM home.css, WHICH ONLY THE HOME PAGE LOADS. /automations/
   uses this exact component for "How yours get built" and was rendering it
   completely unstyled — `display: block`, no grid, no rule above each step, and
   the step numbers as 17px body Inter rather than 11px mono in brand. It read
   as three plain paragraphs, which is exactly why it survived: an unstyled
   component does not look broken, it looks like prose. Every capability page
   ends up wanting this strip, so it lives where every page can see it.

   With no price anywhere on the site, the buyer's unanswered question is not
   "how much" — it is "what am I signing up to, and how long". Answered in time
   and shape. A strip, no card chrome: it is logistics, and it should not
   compete with the sections that argue.
   ============================================================ */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5); }
@media (max-width: 860px) { .steps { grid-template-columns: 1fr; gap: var(--s4); } }
.step { border-top: 1px solid var(--line-2); padding-top: var(--s3); }
.step__n { font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; color: var(--brand); }
.step__t { font-size: var(--t-md); font-weight: 600; color: var(--ink); letter-spacing: -0.02em;
  margin-top: 10px; line-height: 1.15; font-family: var(--display); }
.step__b { font-size: var(--t-sm); line-height: 1.55; color: var(--ink-3); margin-top: 8px; }


/* ============================================================
   PAINTING `--paper-2` AND RE-SOLVING ITS GREYS ARE ONE ACT.

   ⚠️ THIS IS A CLASS OF BUG, NOT AN INSTANCE. `--ink-3` (#6B6B6B) and `--ink-4`
   (#6E6E6E) are answers to the PAPER ground. On `--paper-2` (#EBEDF0) they
   measure 4.49 and 4.29 — both a hair under 4.5. It has now happened SIX times
   by six separate hands: four /s01m/ designs, /s04m/'s alternating band, and
   the /voice-ai/ call card's head and foot. Six authors of the same mistake is
   one missing rule.

   ⚠️ AND THE EXISTING FIX WAS IN THE WRONG FILE. s01m.css carries the same
   invariant as a hand-maintained LIST of class names — and s01m.css is an
   options-page stylesheet that only the /s01m/ picker loads, so it protected
   the four designs that provoked it and nothing else. A list of instances also
   has to be added to, correctly, by everyone who ever paints this colour. That
   is not an invariant, it is a habit.

   So the background and the greys arrive together, in one class, and the only
   way to get the surface is to get the greys with it. Any new paper-2 surface
   uses `.paper2` instead of `background: var(--paper-2)`.
   ============================================================ */
.paper2 { background: var(--paper-2); --ink-3: #585858; --ink-4: #5F5F5F; }
