/* ═══════════════════════════════════════════════════════════════════════════════
   monitorMyLawn — MARKETING DESIGN SYSTEM
   Tokens only. No hex literal may appear in this file; add it to tokens.css.
   Motion: base.css zeroes durations under prefers-reduced-motion, and every
   keyframe animation here is additionally wrapped in a no-preference query.

   ─────────────────────────────────────────────────────────────────────────────
   COMPONENT INDEX — compose from these; do not invent a fourth card grid.
   ─────────────────────────────────────────────────────────────────────────────

   LAYOUT
     .container                 1200px gutter (base.css)
     .container--narrow         760px  — long-form prose
     .container--wide           1320px — figures that need the room
     .section                   vertical rhythm band
       .section--alt            surface fill + hairline top/bottom
       .section--tight          ~60% of the vertical rhythm
       .section--flush-top      no top padding (butts against the band above)
       .section--hairline       hairline on top only, no fill
       .section--dark           EARTH BAND. Re-points --mml-text/-2/-3, --mml-rule,
                                --mml-link, --mml-surface, --mml-border to the cream
                                scale, so ANY component nested inside inverts for
                                free. Use .btn-cream / .btn-outline-cream inside.
     .section__head             eyebrow + h2 + lead, capped at 60ch
     .section__title            centred heading (legacy: still centred)
     .section__title--left      left-aligned variant for editorial sections
     .section__lead .section__cta

   PAGE MASTHEAD  (.pagehero — EVERY page except /home, which has its own hero)
     .pagehero                  the masthead band: sky wash + closing hairline
     .pagehero__grid            [copy | slot] at >=900px, one column below. Both
                                columns hang from ONE hairline (align-items:start) —
                                never set align-items per page, that is the bug that
                                misaligned /support /contact /faq by 14/45/69px
     .pagehero__copy            text column: .eyebrow + h1 + .lede (in that order)
     .pagehero__actions         button row under the lede; .btn-lg reads best
     .pagehero__facts           mono fact line under the buttons; <s> separators
     .pagehero__slot            RIGHT-HAND SLOT — REQUIRED, not decorative. ONE of:
                                (a) .airplate      — live telemetry panel
                                (b) .contents      — "what's on this page" index
                                (c) .pagehero__fig — one figure/diagram + caption
                                Keep it AFTER .pagehero__copy in the DOM: below
                                900px it stacks under the copy, capped at 520px
     .pagehero__fig             unframed figure in a slot; <figcaption> is serif
     .pagehero--tight           shorter band for utility pages (/contact, /support)

   CONTENTS INDEX / JUMP NAV  (.contents — one component, two shapes)
     .contents                  vertical numbered index. Default shape; this is what
                                goes in a .pagehero__slot on a long page
     .contents--rail            horizontal band shape: sticky under the header at
                                >=1000px, in-flow (and side-scrolling) below. Used
                                on /home directly under the hero
     .contents__t               mono label ("Contents" / "On this page")
     .contents__list            the <ol>; add .scroller in the rail shape for the
                                automatic edge fade
     .contents__i .contents__a  row / link; <b> carries the plate number
     [aria-current="true"]      marks the section you are in. Set by home.js, or
                                server-side. No JS ⇒ a plain list of anchors

   EDITORIAL PLATES  (the numbered field-guide signature)
     .plate                     a numbered figure plate; siblings stack with a rule
     .plate__grid               [rail | body] at >=1080px, stacked below
     .plate__rail .plate__no .plate__tick
     .plate__body               min-width:0 — put scrollers in here
     .plate__cap                serif italic figure caption, hairline over it

   TYPE
     .eyebrow                   mono kicker. PROMOTED HERE from faq.css/contact.css
       .eyebrow--rule           adds the leading hairline dash
     .display-1 .display-2 .display-3   display scale (clamped)
     .lede                      large intro paragraph, 62ch
     .mono                      uppercase mono micro-label
     .tiny                      .8rem tertiary note
     .measure                   65ch cap
     .num                       tabular-nums mono inline figure
     .mark                      hand-drawn underline on an inline phrase

   STAT / TRUST BANDS
     .trustrail  .trustrail__i  .trustrail__k  .trustrail__v
                                hairline-divided N-up rail of TRUE facts
     .statband   .statband__i   .statband__k   .statband__v
                                instrument strip: mono key over a big mono value
     .bignum                    display-size figure with a <sup> unit
     .hairgrid                  generic hairline-divided auto grid
       .hairgrid--2 --3 --4     column caps at the top breakpoint

   FEATURE ROWS & TRACKS
     .featurerow  .featurerow__art  .featurerow__body  (+ .featurerow--flip)
     .steptrack   .steptrack__step  .steptrack__n  .steptrack__art
     .toolindex   .toolindex__i     .toolindex__n    .toolindex__io
     .timeline    .timeline__i

   TABLES & SPECS
     .cmp                       editorial comparison table (hairline rows)
       .cmp__yes .cmp__no .cmp__part
     .specgrid  .specgrid__row  .specgrid__k  .specgrid__v
     .spec-tbc                  UNCONFIRMED hardware value. Renders as a visible
                                placeholder chip. NEVER replace with a guess.

   DISCLOSURE / CALLOUTS
     .accordion  .accordion__i  (a <details>)
     .callout  (+ .callout--warn .callout--info)
     .pullquote
     .notecard  .notecard__k  .notecard__v  .notecard__n

   DATA-VIZ FRAMES
     .vizframe  .vizframe__head  .vizframe__t  .vizframe__key  .vizframe__body
                .vizframe__foot
     .scroller  .scrollhint      horizontal escape hatch for wide figures
     .browserframe  __bar __url __chip
     .soilTxt                   SVG text drawn on soil: cream ink + dark halo via
                                paint-order, so it holds AA on tan OR on black

   CONTROLS
     .btn-cream .btn-outline-cream     for use inside .section--dark
     .rangefield  __row __out          calculator slider
     .chip                             small mono pill
     .pausebtn                         play/pause for an animated figure

   MOTION
     .reveal + [data-d="1".."4"]       fade/rise on enter, staggered.
                                       Under reduce: fully visible on first paint.
   ═══════════════════════════════════════════════════════════════════════════════ */

::selection { background: var(--mml-selection); }

/* ═══ STICKY GEOMETRY ═════════════════════════════════════════════════════════
   Layout constants, NOT design tokens — they carry no colour, so they belong here
   rather than in tokens.css. They exist because "the top of the readable page" was
   hard-coded in four places (86px on .plate__rail, 92px on .toolindex__plate, 116px
   and 86px in faq.css) and adding a sticky rail under the header silently overlapped
   every one of them.
     --hdr-h       .site-header min-height.
     --rail-h      extra height a STICKY .contents--rail adds under the header. 0 by
                   default, so every existing sticky keeps its previous value to the
                   pixel; the rail itself opts in (see .contents--rail below).
     --stick-top   where a sticky in-page rail may start.
     --anchor-top  scroll-margin-top for an in-page anchor target. */
:root {
  --hdr-h: 62px;
  --rail-h: 0px;
  --stick-top: calc(var(--hdr-h) + var(--rail-h) + var(--sp-2xl));
  --anchor-top: calc(var(--hdr-h) + var(--rail-h) + var(--sp-sm));
}
/* Anchor targets clear the sticky header (and the rail, where there is one) instead
   of landing underneath it. base.css already forces scroll-behavior:auto under
   prefers-reduced-motion, so the jump is instant for anyone who asked for that. */
.hero[id], .pagehero[id], .plate[id], .section[id] { scroll-margin-top: var(--anchor-top); }

/* ═══ PUBLIC HEADER ═══════════════════════════════════════════════════════════ */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(var(--mml-surface-rgb), .8);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  backdrop-filter: blur(12px) saturate(1.4);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, box-shadow .2s ease;
}
/* No blur support → fall back to a solid surface so text stays readable. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header { background: var(--mml-surface); }
}
/* .is-scrolled is toggled by the tiny inline script in header-public.php. */
.site-header.is-scrolled { border-bottom-color: var(--mml-border); box-shadow: var(--shadow-sm); }

.site-header__inner { display: flex; align-items: center; gap: var(--sp-lg); min-height: 62px; }
.brand { display: inline-flex; align-items: center; gap: var(--sp-sm); font-weight: 700; color: var(--mml-text); }
.brand:hover { text-decoration: none; }
.brand__mark { color: var(--mml-primary); transition: transform .2s ease; }
svg.brand__mark { width: 26px; height: 26px; flex: none; }
.brand:hover .brand__mark { transform: rotate(-8deg) scale(1.06); }
.brand__name { letter-spacing: -.025em; font-size: 1.05rem; }
/* --mml-primary as 17px text measures 3.77:1 on the header. --mml-link is the
   text-safe green: 6.52:1 light, 5.87:1 dark, and it inverts inside .site-footer
   because that block re-points --mml-link. */
.brand__name strong { color: var(--mml-link); }
.brand--compact .brand__name { font-size: .95rem; }

.site-nav { margin-left: auto; }
.nav-menu { list-style: none; display: flex; gap: var(--sp-lg); margin: 0; padding: 0; }
.nav-menu a { position: relative; display: inline-block; padding: .4rem 0; color: var(--mml-text-2); font-weight: 500; font-size: .9rem; }
.nav-menu a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  border-radius: var(--r-pill); background: var(--mml-primary);
  transform: scaleX(0); transform-origin: center; transition: transform .18s ease;
}
.nav-menu a:hover, .nav-menu a[aria-current="page"] { color: var(--mml-link); text-decoration: none; }
.nav-menu a:hover::after, .nav-menu a[aria-current="page"]::after { transform: scaleX(1); }
.nav-menu a[aria-current="page"] { font-weight: 600; }
.site-header__actions { display: flex; align-items: center; gap: var(--sp-sm); }
.nav-toggle { display: none; }
.theme-toggle { padding: .5rem .6rem; }

/* ═══ BUTTONS ════════════════════════════════════════════════════════════════
   The .btn-primary AA repair that used to live here has been applied at source in
   components.css, so /app and /admin get it too. Duplicating it here as well is how
   the two copies drift apart — the same trap .eyebrow fell into. */
.btn-lg { font-size: 1rem; padding: .85rem 1.35rem; border-radius: var(--r-lg); }
.btn-cream { background: var(--mml-cream); color: var(--mml-cream-ink); border-color: transparent; }
.btn-cream:hover { background: var(--mml-cream); filter: brightness(1.04); color: var(--mml-cream-ink); }
.btn-outline-cream { background: transparent; color: var(--mml-cream); border-color: rgba(var(--mml-cream-rgb), .42); }
.btn-outline-cream:hover { border-color: var(--mml-cream); background: rgba(var(--mml-cream-rgb), .09); color: var(--mml-cream); }

/* ═══ SECTIONS ════════════════════════════════════════════════════════════════ */
.section { padding: var(--section-pad) 0; }
.section--alt { background: var(--mml-surface); border-top: 1px solid var(--mml-border); border-bottom: 1px solid var(--mml-border); }
.section--tight { padding-block: calc(var(--section-pad) * .6); }
.section--flush-top { padding-top: 0; }
.section--hairline { border-top: 1px solid var(--mml-rule); }
.section__title { text-align: center; font-size: clamp(1.5rem, 1.25rem + 1.2vw, 2rem); letter-spacing: -.01em; }
.section__title--left { text-align: left; }
.section__lead { text-align: center; max-width: 60ch; margin: 0 auto var(--sp-2xl); }
.section__title--left + .section__lead { text-align: left; margin-inline: 0; }
.section__cta { text-align: center; margin-top: var(--sp-2xl); }
.container--narrow { max-width: 760px; }
.container--wide { max-width: 1320px; }

.section__head { max-width: 60ch; margin-bottom: var(--sp-3xl); }
.section__head h2 { margin-bottom: var(--sp-md); }
.section__head .lede { margin-bottom: 0; }

/* THE EARTH BAND. Re-points the ink tokens so nested components invert for free. */
.section--dark {
  --mml-text: var(--mml-cream);
  --mml-text-2: var(--mml-cream-2);
  --mml-text-3: var(--mml-cream-3);
  --mml-rule: rgba(var(--mml-cream-rgb), .16);
  --mml-rule-strong: rgba(var(--mml-cream-rgb), .3);
  --mml-border: rgba(var(--mml-cream-rgb), .16);
  --mml-link: var(--mml-primary-light);
  --mml-heading-accent: var(--mml-primary-light);
  --mml-surface: var(--mml-earth-2);
  --mml-surface-hover: var(--mml-earth-2);
  position: relative; isolation: isolate;
  background: var(--mml-earth); color: var(--mml-cream);
}
.section--dark h2, .section--dark h3, .section--dark h4 { color: var(--mml-cream); }
/* WCAG 1.4.1: an inline link inside cream-3 body copy is not distinguishable by
   colour alone at these luminances, so it carries an underline. */
.section--dark p a { text-decoration: underline; text-underline-offset: .18em; }
.section--dark .muted { color: var(--mml-cream-2); }
.section--dark::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(80% 120% at 18% -10%, rgba(var(--mml-primary-rgb), .22), transparent 60%),
    radial-gradient(70% 90% at 92% 112%, rgba(139, 94, 52, .3), transparent 66%);
}

/* ═══ PAGE MASTHEAD ═══════════════════════════════════════════════════════════
   .pagehero is the shared two-column masthead for every page that is not /home.
   It exists because the old left-aligned .pagehead / .helpmast blocks stopped at
   68ch and left 46% of a 1440px masthead empty — the one place the site stopped
   reading as a single design. The homepage hero fills its width because it is a
   COMPOSED statement (text column + telemetry panel over a full-bleed figure);
   this gives every other page the same shape with a slot for whichever of those
   three kinds of right-hand content that page actually has.

   MARKUP CONTRACT
     <section class="pagehero" aria-labelledby="x-h1">
       <div class="container pagehero__grid">
         <div class="pagehero__copy">
           <p class="eyebrow eyebrow--rule">Kicker</p>
           <h1 class="display-1" id="x-h1">…</h1>
           <p class="lede">…</p>
           <div class="pagehero__actions">…btn btn-lg…</div>      (optional)
           <p class="pagehero__facts">…<s>·</s>…</p>              (optional)
         </div>
         <div class="pagehero__slot">…ONE of .airplate / .contents / .pagehero__fig…</div>
       </div>
     </section>
   The slot MUST stay after the copy in source order — that is what makes the
   single-column collapse read in the right order on a phone.                   */
.pagehero {
  position: relative; overflow: hidden;
  /* The same three-layer sky wash as .hero, at ~80% strength: enough to make the
     two mastheads siblings, not enough to compete with a page that has no figure.
     CONTRAST: the two radials are centred ABOVE the band, so their peak alpha
     anywhere inside it is 0.047 — the effective background stays sky-1..sky-2.
     Sampled on a 20x10px grid across the whole 1440x330 band, the minimum measured
     ratio is: h1 --mml-text 14.48:1 light / 15.04:1 dark · .lede + .pagehero__facts
     + .contents__a --mml-text-2 5.05 / 7.51 · .contents__t + figcaption
     --mml-text-3 4.77 / 5.97 · .eyebrow --mml-link 5.83 / 6.07 · a marked
     .contents__a on its 10% primary tint 5.22 / 5.40. All clear AA. Raising either
     radial's alpha eats that headroom — re-measure if you do. */
  background:
    radial-gradient(110% 62% at 82% -22%, rgba(var(--mml-primary-rgb), .11), transparent 62%),
    radial-gradient(78% 46% at 2% -14%, rgba(245, 158, 11, .07), transparent 58%),
    linear-gradient(var(--mml-sky-1), var(--mml-sky-2));
  border-bottom: 1px solid var(--mml-rule);
}
.pagehero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-2xl);
  /* ── THE SHARED BASELINE ──────────────────────────────────────────────────
     Both columns hang from the grid row's start edge, which is the hairline
     directly above them, so the eyebrow and the slot's first box always begin on
     the same line no matter how long either column turns out to be. This is the
     fix for the measured bug: .helpmast used `align-items: end`, which bottom-
     aligns instead, and the same shared pattern therefore landed 14px out on
     /support, 45px out on /contact and 69px out on /faq. Do NOT re-declare
     align-items on .pagehero__grid in a page-level sheet or a style attribute. */
  align-items: start;
  border-top: 1px solid var(--mml-rule);
  margin-top: clamp(1.1rem, .85rem + 1.1vw, 1.8rem);
  padding-top: clamp(1.3rem, 1rem + 1.3vw, 2rem);
  padding-bottom: clamp(1.6rem, 1.2rem + 1.8vw, 2.6rem);
}
@media (min-width: 900px) {
  .pagehero__grid { grid-template-columns: minmax(0, 1.32fr) minmax(290px, .68fr); gap: 0 var(--sp-3xl); }
  /* Pin BOTH tracks and the row, rather than trusting auto-placement: a page that
     puts the slot first in the DOM still lays out correctly here (pinning only the
     column makes sparse auto-placement drop the copy into row 2 and stack them).
     Only the documented single-column reading order below 900px would be wrong. */
  .pagehero__copy { grid-area: 1 / 1; }
  .pagehero__slot { grid-area: 1 / 2; }
  /* THE SLOT IS NOT OPTIONAL — but if one is missing or left empty, fall back to a
     single column rather than re-opening the 46% hole this component was built to
     close. Silent degradation beats a masthead that looks unfinished in production. */
  .pagehero__grid:not(:has(> .pagehero__slot *)) { grid-template-columns: minmax(0, 1fr); }
}
.pagehero__copy, .pagehero__slot { min-width: 0; }
/* Baseline guard: a collapsed/added top margin on either column's first child would
   silently reintroduce the misalignment this component exists to prevent. */
.pagehero__copy > :first-child, .pagehero__slot > :first-child { margin-top: 0; }
.pagehero__copy h1 { margin: 0 0 var(--sp-lg); }
.pagehero__copy .lede { margin-bottom: 0; }
.pagehero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-md); margin: var(--sp-xl) 0 0; }
/* Same treatment as .hero__note: this line carries price, cancellation and the
   radios, so it is set at ~13px in the mono face rather than as fine print. */
.pagehero__facts {
  margin: var(--sp-md) 0 0; color: var(--mml-text-2);
  font-family: var(--font-mono); font-size: .82rem; letter-spacing: .04em;
  display: flex; flex-wrap: wrap; gap: .4rem .8rem; align-items: center;
}
.pagehero__facts s { text-decoration: none; color: var(--mml-ink-dec); }
/* Slot kind (c): one figure, unframed. Use .vizframe instead when the figure needs
   a titled panel, or .browserframe when it is a screenshot. */
.pagehero__fig { margin: 0; min-width: 0; }
.pagehero__fig > svg, .pagehero__fig > img { width: 100%; height: auto; display: block; }
.pagehero__fig > figcaption {
  font-family: var(--font-serif); font-style: italic; font-size: .86rem;
  color: var(--mml-text-3); line-height: 1.5;
  margin-top: var(--sp-md); padding-top: var(--sp-sm); border-top: 1px solid var(--mml-rule);
}
.pagehero--tight .pagehero__grid { padding-bottom: clamp(1.1rem, .9rem + 1vw, 1.7rem); }
@media (max-width: 899px) {
  /* One column. The slot keeps a panel-sized measure so it reads as an attached
     plate rather than a stranded orphan stretched across the whole screen — the
     same 520px cap .hero__plate / .hero__log already use below their breakpoint.
     The row gap opens up because the slot now follows .pagehero__facts, and two
     mono micro-labels 24px apart read as one block. */
  .pagehero__grid { gap: var(--sp-3xl); }
  .pagehero__slot { max-width: 520px; }
}
@media (max-width: 560px) {
  /* Full-bleed stacked CTAs read as targets; content-width ones read as ragged. */
  .pagehero__actions { flex-direction: column; align-items: stretch; }
  .pagehero__actions .btn { width: 100%; justify-content: center; }
}

/* ═══ CONTENTS INDEX / JUMP NAV ═══════════════════════════════════════════════
   ONE component with two shapes, because they are the same thing: a numbered list
   of the plates on this page. The FIG.01–08 rails are already numbered, so this is
   the field-manual contents page rather than a bolted-on widget.
     .contents         vertical index — the (b) slot of a .pagehero
     .contents--rail   horizontal band — /home, directly under the hero; sticky
                       under the header from 1000px up
   No JS is required: it is an <ol> of real in-page anchors, and .contents__a
   picks up [aria-current="true"] when a script is there to set it.            */
.contents { min-width: 0; }
.contents__t {
  display: block; margin: 0 0 var(--sp-sm); padding-bottom: var(--sp-sm);
  border-bottom: 1px solid var(--mml-rule-strong);
  font-family: var(--font-mono); font-size: .62rem; letter-spacing: .15em;
  text-transform: uppercase; font-weight: 700; color: var(--mml-text-3);
}
.contents__list { list-style: none; margin: 0; padding: 0; min-width: 0; }
.contents__i { border-bottom: 1px solid var(--mml-rule); min-width: 0; }
.contents__i:last-child { border-bottom: 0; }
/* Fixed number column so the labels line up down the list (same idea as
   .toolindex__i). The negative inline margin lets the hover/current tint break the
   measure while the TEXT stays flush with the header rule — the trick .airplate .hi
   already uses, so it reads as part of the system rather than a one-off. */
.contents__a {
  display: grid; grid-template-columns: 1.6rem minmax(0, 1fr); gap: .3rem;
  align-items: baseline; padding: .46rem .5rem; margin-inline: -.5rem;
  border-radius: var(--r-sm); color: var(--mml-text-2); font-size: .9rem; line-height: 1.45;
}
.contents__a b {
  font-family: var(--font-mono); font-size: .66rem; font-weight: 800; letter-spacing: .08em;
  color: var(--mml-text-3); font-variant-numeric: tabular-nums;
}
.contents__a:hover { color: var(--mml-link); background: rgba(var(--mml-primary-rgb), .06); text-decoration: none; }
.contents__a:hover b { color: var(--mml-link); }
/* The section you are in. Colour is not the only channel: the row also takes a tint
   in the vertical shape and a 2px underscore in the rail shape. */
.contents__a[aria-current="true"] { color: var(--mml-link); font-weight: 650; background: rgba(var(--mml-primary-rgb), .1); }
.contents__a[aria-current="true"] b { color: var(--mml-link); }

.contents--rail {
  background: var(--mml-surface);
  border-top: 1px solid var(--mml-rule);
  border-bottom: 1px solid var(--mml-rule);
}
/* min-height pins the rail to exactly --rail-h (45 + the two 1px borders), so the
   constant every other sticky element reads cannot drift out of step with the
   rail's actual rendered height. */
.contents--rail > .container { display: flex; align-items: center; gap: var(--sp-md); min-height: 45px; min-width: 0; }
.contents--rail .contents__t { flex: none; margin: 0; padding: 0; border: 0; }
.contents--rail .contents__list {
  display: flex; align-items: stretch; gap: .1rem; flex: 1; min-width: 0;
  overflow-x: auto;
  /* 5px clears a 2px focus ring at 2px offset, so .scroller's overflow-y:hidden
     cannot clip the outline on a keyboard-focused chip. */
  padding-block: 5px;
  scrollbar-width: none;
}
.contents--rail .contents__list::-webkit-scrollbar { display: none; }
.contents--rail .contents__i { border-bottom: 0; flex: none; }
/* Tight, because ELEVEN of these have to fit one 1200px row at 1440px. */
.contents--rail .contents__a {
  display: inline-flex; align-items: baseline; gap: .38rem; white-space: nowrap;
  margin: 0; padding: .38rem .44rem; font-size: .83rem;
}
.contents--rail .contents__a[aria-current="true"] { box-shadow: inset 0 -2px 0 var(--mml-primary); }
@media (min-width: 1000px) {
  /* The rail becomes page chrome, so everything else that sticks has to clear it.
     One declaration does that for .plate__rail, .toolindex__plate and every anchor
     target, because they all read --rail-h. :has() is already a dependency of this
     sheet (see the .site-footer rule); where it is unsupported the only cost is
     that a sticky FIG number can pass under the rail. */
  html:has(.contents--rail) { --rail-h: 47px; }
  .contents--rail { position: sticky; top: var(--hdr-h); z-index: 30; }
}
@media (max-width: 999px) {
  /* Not sticky on a phone — it would eat a tenth of the screen for the whole
     document. It stays in flow immediately under the hero, so a reader still meets
     it before the first plate, and the LIST scrolls sideways inside itself, which
     is why the document never does. */
  .contents--rail > .container { gap: var(--sp-sm); }
  .contents--rail .contents__t { font-size: .56rem; letter-spacing: .1em; }
}

/* ═══ EDITORIAL PLATES ════════════════════════════════════════════════════════ */
.plate { padding-block: var(--section-pad); position: relative; }
.plate + .plate { border-top: 1px solid var(--mml-rule); }
.plate__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-lg); min-width: 0; }
.plate__body { min-width: 0; }
@media (min-width: 1080px) {
  .plate__grid { grid-template-columns: 104px minmax(0, 1fr); gap: 0; }
  /* height:0 keeps the sticky rail from padding the row it lives in. --stick-top is
     62+0+24 = the same 86px this had hard-coded, and it grows by itself on a page
     that carries a sticky .contents--rail. */
  .plate__rail { flex-direction: column; align-items: flex-start; gap: .75rem; position: sticky; top: var(--stick-top); align-self: start; height: 0; }
  .plate__tick { width: 1px; height: 140px; flex: none; max-width: none; background: linear-gradient(var(--mml-rule-strong), transparent); }
}
.plate__rail { display: flex; align-items: center; gap: .7rem; }
.plate__no {
  font-family: var(--font-mono); font-size: .68rem; letter-spacing: .16em;
  font-weight: 700; color: var(--mml-text-3); white-space: nowrap;
}
.plate__no b { color: var(--mml-link); font-weight: 800; }
.plate__tick { flex: 1; height: 1px; background: var(--mml-rule); max-width: 120px; }
.plate__cap {
  font-family: var(--font-serif); font-style: italic; font-size: .9rem;
  color: var(--mml-text-3); line-height: 1.5; max-width: 74ch;
  padding-top: var(--sp-md); border-top: 1px solid var(--mml-rule); margin-top: var(--sp-2xl);
}

/* ═══ TYPE ════════════════════════════════════════════════════════════════════ */
/* .eyebrow lived in faq.css + contact.css while this sheet was mid-rewrite. It is
   the canonical definition now — those two copies can be deleted. */
.eyebrow {
  display: flex; align-items: center; gap: var(--sp-sm);
  margin: 0 0 var(--sp-sm);
  font-family: var(--font-mono);
  font-size: .72rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--mml-link);
}
.eyebrow--rule::before { content: ""; width: 22px; height: 1px; background: currentColor; opacity: .65; flex: none; }

.display-1 { font-size: clamp(2.15rem, 1.35rem + 2.85vw, 3.6rem); line-height: 1.03; letter-spacing: -.03em; font-weight: 800; }
.display-2 { font-size: clamp(1.9rem, 1.35rem + 2vw, 3rem);       line-height: 1.05; letter-spacing: -.028em; font-weight: 800; }
.display-3 { font-size: clamp(1.35rem, 1.15rem + .8vw, 1.85rem);  line-height: 1.15; letter-spacing: -.022em; font-weight: 750; }
.display-1, .display-2, .display-3 { text-wrap: balance; }

.lede { font-size: clamp(1.02rem, .96rem + .34vw, 1.2rem); color: var(--mml-text-2); line-height: 1.62; max-width: 62ch; }
.mono { font-family: var(--font-mono); font-size: .68rem; letter-spacing: .13em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); }
.tiny { font-size: .8rem; color: var(--mml-text-3); line-height: 1.55; }
.measure { max-width: 65ch; }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--mml-text); letter-spacing: -.01em; }

/* Hand-drawn underline. JS adds .is-in when the phrase scrolls into view. */
.mark { position: relative; white-space: nowrap; display: inline-block; }
.mark svg { position: absolute; left: -.04em; bottom: -.1em; width: 100.8%; height: .34em; overflow: visible; pointer-events: none; }
.mark path { fill: none; stroke: var(--mml-primary); stroke-width: 4.6; stroke-linecap: round; stroke-dasharray: 250; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: no-preference) {
  .mark path { stroke-dashoffset: 250; }
  .mark.is-in path { stroke-dashoffset: 0; transition: stroke-dashoffset 1.05s cubic-bezier(.2,.7,.3,1) .3s; }
}

/* ═══ TRUST RAIL / STAT BAND / HAIRGRID ═══════════════════════════════════════ */
/* Usable on a <ul>/<ol> as well as a <div>, so it resets list chrome itself. */
.hairgrid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; border-top: 1px solid var(--mml-rule); list-style: none; margin: 0; padding: 0; }
.hairgrid > * { padding: var(--sp-lg) var(--sp-lg) var(--sp-lg) 0; border-bottom: 1px solid var(--mml-rule); min-width: 0; }
@media (min-width: 680px) {
  .hairgrid--2, .hairgrid--3, .hairgrid--4 { grid-template-columns: 1fr 1fr; }
  .hairgrid > * { border-right: 1px solid var(--mml-rule); padding-left: var(--sp-lg); }
  .hairgrid--2 > :nth-child(2n), .hairgrid--3 > :nth-child(2n), .hairgrid--4 > :nth-child(2n) { border-right: 0; }
  .hairgrid > :first-child { padding-left: 0; }
}
@media (min-width: 1000px) {
  .hairgrid--3 { grid-template-columns: repeat(3, 1fr); }
  .hairgrid--4 { grid-template-columns: repeat(4, 1fr); }
  .hairgrid--5 { grid-template-columns: repeat(5, 1fr); }
  .hairgrid--3 > *, .hairgrid--4 > *, .hairgrid--5 > * { border-bottom: 0; border-right: 1px solid var(--mml-rule); }
  .hairgrid--3 > :nth-child(2n), .hairgrid--4 > :nth-child(2n) { border-right: 1px solid var(--mml-rule); }
  .hairgrid--3 > :last-child, .hairgrid--4 > :last-child, .hairgrid--5 > :last-child { border-right: 0; }
  .hairgrid--3, .hairgrid--4, .hairgrid--5 { border-bottom: 1px solid var(--mml-rule); }
}
.hairgrid .k { display: block; font-family: var(--font-mono); font-size: .6rem; letter-spacing: .15em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; margin-bottom: var(--sp-xs); }
.hairgrid .v { display: block; font-size: .93rem; line-height: 1.5; color: var(--mml-text); font-weight: 550; }

.trustrail { list-style: none; margin: 0; padding: 0; }
.trustrail__i h3 { font-size: .95rem; margin: 0 0 var(--sp-xs); letter-spacing: -.01em; }
.trustrail__i p { font-size: .85rem; color: var(--mml-text-2); margin: 0; line-height: 1.55; }
.trustrail__ic { width: 20px; height: 20px; color: var(--mml-link); margin-bottom: var(--sp-sm); display: block; }

.statband { border-top: 1px solid var(--mml-rule); border-bottom: 1px solid var(--mml-rule); background: rgba(var(--mml-surface-rgb), .55); position: relative; z-index: 2; }
.statband__in { display: flex; flex-wrap: wrap; align-items: stretch; }
.statband__i { flex: 1 1 auto; min-width: 138px; padding: .7rem 0; display: flex; flex-direction: column; gap: .1rem; border-right: 1px solid var(--mml-rule); }
.statband__i:last-child { border-right: 0; }
.statband__k { font-family: var(--font-mono); font-size: .6rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; }
.statband__v { font-family: var(--font-mono); font-size: 1rem; font-weight: 700; color: var(--mml-text); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.statband__v.is-warn { color: var(--mml-viz-warn); }
.statband__v.is-water { color: var(--mml-viz-moist); }
@media (max-width: 760px) {
  .statband__i { min-width: 50%; border-right: 0; }
  .statband__i:nth-child(odd) { border-right: 1px solid var(--mml-rule); padding-right: var(--sp-md); }
  .statband__i:nth-child(even) { padding-left: var(--sp-md); }
}

.bignum { font-size: clamp(2.4rem, 1.9rem + 2.2vw, 3.4rem); font-weight: 800; letter-spacing: -.04em; line-height: .95; font-variant-numeric: tabular-nums; color: var(--mml-viz-danger); }
.bignum sup { font-size: .34em; font-weight: 700; letter-spacing: .06em; vertical-align: .95em; margin-left: .14em; color: var(--mml-text-3); }
.bignum--good { color: var(--mml-link); }

.chip {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--font-mono); font-size: .6rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 700;
  padding: .22rem .5rem; border-radius: var(--r-sm); border: 1px solid var(--mml-rule); color: var(--mml-text-3);
}
.chip--live { color: var(--mml-link); border-color: rgba(var(--mml-primary-rgb), .45); background: rgba(var(--mml-primary-rgb), .09); }
.chip--warn { color: var(--mml-viz-warn); border-color: var(--mml-viz-warn); }

/* the pulsing "live" dot */
.livedot { width: 7px; height: 7px; border-radius: 50%; background: var(--mml-primary); position: relative; flex: none; display: inline-block; }
.livedot::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1.5px solid var(--mml-primary); opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .livedot::after { animation: mml-ping 2.4s cubic-bezier(.2,.7,.3,1) infinite; }
  html.is-paused .livedot::after { animation-play-state: paused; }
}
@keyframes mml-ping { 0% { transform: scale(.55); opacity: .9; } 70%, 100% { transform: scale(1.5); opacity: 0; } }

/* ═══ FEATURE ROWS & TRACKS ═══════════════════════════════════════════════════ */
.featurerow { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2xl); align-items: center; min-width: 0; }
.featurerow + .featurerow { margin-top: var(--section-pad); }
@media (min-width: 900px) {
  .featurerow { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-3xl); }
  .featurerow--flip .featurerow__art { order: 2; }
}
.featurerow__art { min-width: 0; }
.featurerow__art svg { width: 100%; height: auto; display: block; }
/* A tall, narrow figure (the soil core is 200x470) would otherwise be blown up to
   the full column width and stand 1200px tall. Cap the intrinsic width instead. */
.featurerow__art--slim svg { max-width: 224px; margin-inline: auto; }
.featurerow__body { min-width: 0; }

.steptrack { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3xl); }
@media (min-width: 900px) { .steptrack { grid-template-columns: repeat(3, 1fr); gap: 0; } }
.steptrack__step { position: relative; min-width: 0; }
@media (min-width: 900px) {
  .steptrack__step { padding-inline: var(--sp-2xl); }
  .steptrack__step:first-child { padding-left: 0; }
  .steptrack__step:last-child { padding-right: 0; }
  .steptrack__step + .steptrack__step { border-left: 1px solid var(--mml-rule); }
}
.steptrack__n { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .16em; font-weight: 800; color: var(--mml-link); display: flex; align-items: center; gap: .6rem; margin-bottom: var(--sp-md); }
/* .steptrack__k, not <s>: these are category labels ("Identity", "Radio", "Timing"),
   and <s> means retracted/no-longer-accurate — a screen reader announces it as struck
   through. <s> is fine for the purely decorative middot separators elsewhere (those
   carry aria-hidden), but not for words a reader is meant to take at face value. */
.steptrack__n .steptrack__k { text-decoration: none; color: var(--mml-text-3); font-weight: 600; letter-spacing: .09em; }
.steptrack__art { border: 1px solid var(--mml-border); border-radius: var(--r-xl); background: var(--mml-surface-hover); overflow: hidden; margin-bottom: var(--sp-lg); }
.steptrack__art svg { width: 100%; height: auto; display: block; }
.steptrack__step h3 { margin-bottom: var(--sp-sm); font-size: 1.15rem; letter-spacing: -.018em; }
.steptrack__step p { font-size: .93rem; color: var(--mml-text-2); line-height: 1.6; }
.steptrack__step code { font-family: var(--font-mono); font-size: .82em; background: var(--mml-surface-hover); border: 1px solid var(--mml-rule); padding: .1em .38em; border-radius: var(--r-sm); color: var(--mml-text); }

/* the eight-tool index spread */
.toolindex { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2xl); min-width: 0; }
@media (min-width: 1000px) { .toolindex { grid-template-columns: 300px minmax(0, 1fr); gap: var(--sp-3xl); align-items: start; } }
.toolindex__plate { display: none; }
@media (min-width: 1000px) {
  /* calc(--stick-top + 6px) = the same 92px this had hard-coded. */
  .toolindex__plate { display: block; position: sticky; top: calc(var(--stick-top) + 6px); border: 1px solid var(--mml-border); border-radius: var(--r-xl); background: var(--mml-surface); overflow: hidden; box-shadow: var(--shadow-sm); }
  .toolindex__plate svg { width: 100%; height: auto; }
  /* Both selectors are (0,2,0) so the .is-on rule wins on source order. An earlier
     `.toolindex__plate svg { display:block }` out-specified a bare `.toolindex__fig`
     and every one of the eight figures rendered at once. */
  .toolindex__plate .toolindex__fig { display: none; }
  .toolindex__plate .is-on { display: block; }
}
.toolindex__cap { padding: var(--sp-md) var(--sp-lg) var(--sp-lg); border-top: 1px solid var(--mml-rule); }
.toolindex__cap .k { display: block; font-family: var(--font-mono); font-size: .6rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; margin-bottom: var(--sp-xs); }
.toolindex__cap .v { font-size: .88rem; color: var(--mml-text-2); line-height: 1.5; }
.toolindex__list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--mml-rule); }
.toolindex__i { border-bottom: 1px solid var(--mml-rule); padding: var(--sp-lg) 0; display: grid; grid-template-columns: 2.6rem minmax(0, 1fr); gap: var(--sp-md); }
.toolindex__i:hover, .toolindex__i:focus-within { background: rgba(var(--mml-primary-rgb), .04); }
.toolindex__n { font-family: var(--font-mono); font-size: .8rem; font-weight: 800; color: var(--mml-link); letter-spacing: .04em; padding-top: .12rem; }
.toolindex__i h3 { font-size: 1.05rem; margin: 0 0 .3rem; letter-spacing: -.018em; }
.toolindex__i > div > p { font-size: .9rem; color: var(--mml-text-2); margin: 0 0 var(--sp-sm); line-height: 1.55; }
.toolindex__io { display: grid; gap: .25rem; font-family: var(--font-mono); font-size: .7rem; line-height: 1.5; color: var(--mml-text-3); }
.toolindex__io b { color: var(--mml-text-2); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-size: .62rem; margin-right: .4rem; }
.toolindex__io em { font-style: normal; color: var(--mml-text); }

.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline__i { position: relative; padding: 0 0 var(--sp-xl) var(--sp-2xl); border-left: 1px solid var(--mml-rule); }
.timeline__i:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline__i::before { content: ""; position: absolute; left: -5px; top: .35rem; width: 9px; height: 9px; border-radius: 50%; background: var(--mml-primary); }
.timeline__i .k { display: block; font-family: var(--font-mono); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; margin-bottom: var(--sp-xs); }

/* ═══ TABLES & SPECS ══════════════════════════════════════════════════════════ */
.cmp { width: 100%; border-collapse: collapse; font-size: .9rem; min-width: 620px; }
.cmp caption { text-align: left; font-family: var(--font-mono); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; padding-bottom: var(--sp-md); }
.cmp th, .cmp td { text-align: left; padding: var(--sp-md) var(--sp-md); border-bottom: 1px solid var(--mml-rule); vertical-align: top; }
.cmp thead th { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .13em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; border-bottom: 1px solid var(--mml-rule-strong); }
.cmp thead th:last-child { color: var(--mml-link); }
.cmp tbody th { font-weight: 600; color: var(--mml-text); width: 27%; }
.cmp td { color: var(--mml-text-2); }
.cmp tbody tr:last-child th, .cmp tbody tr:last-child td { border-bottom: 0; }
.cmp td:last-child { color: var(--mml-text); background: rgba(var(--mml-primary-rgb), .05); }
.cmp__yes, .cmp__no, .cmp__part { display: inline-flex; align-items: center; gap: .4rem; font-family: var(--font-mono); font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 700; }
.cmp__yes { color: var(--mml-link); }
.cmp__no { color: var(--mml-viz-danger); }
.cmp__part { color: var(--mml-viz-warn); }

.specgrid { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--mml-rule); }
.specgrid__row { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem var(--sp-md); justify-content: space-between; padding: .7rem 0; border-bottom: 1px solid var(--mml-rule); }
.specgrid__k { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .13em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; }
.specgrid__v { font-family: var(--font-mono); font-size: .84rem; font-weight: 650; color: var(--mml-text); text-align: right; }
/* An UNCONFIRMED hardware number. Deliberately loud. Never swap in a guess. */
.spec-tbc {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--font-mono); font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 700;
  /* Ink is --mml-warning-fg, NOT --mml-viz-warn: over the 8% amber wash on a light
     .plate the composite measured 4.37:1 at 11px, under the AA floor. Dropping the
     wash and switching the ink gives 4.71:1 light / 12.57:1 dark, and the chip stays
     just as loud because the dashed amber border carries the alarm (border is
     non-text and only needs 3:1 — it has 4.65:1). product-pages.css previously
     patched its own copy; this is the canonical fix, so that override is redundant. */
  color: var(--mml-warning-fg); border: 1px dashed var(--mml-viz-warn); border-radius: var(--r-sm);
  padding: .1rem .42rem; background: none;
}

/* ═══ DISCLOSURE / CALLOUTS ═══════════════════════════════════════════════════ */
.accordion { border-top: 1px solid var(--mml-rule); }
.accordion__i { border-bottom: 1px solid var(--mml-rule); }
.accordion__i summary {
  cursor: pointer; list-style: none; display: flex; gap: var(--sp-md); align-items: baseline;
  padding: var(--sp-lg) 0; font-weight: 600; font-size: 1rem; color: var(--mml-text); letter-spacing: -.012em;
}
.accordion__i summary::-webkit-details-marker { display: none; }
.accordion__i summary::after {
  content: "+"; margin-left: auto; font-family: var(--font-mono); font-size: 1.1rem;
  color: var(--mml-text-3); line-height: 1; transition: transform .18s ease;
}
.accordion__i[open] summary::after { content: "\2212"; }
.accordion__i summary:hover { color: var(--mml-link); }
.accordion__i summary .n { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .12em; color: var(--mml-text-3); font-weight: 700; flex: none; }
.accordion__i > p { margin: 0 0 var(--sp-lg); padding-left: 2.3rem; color: var(--mml-text-2); font-size: .93rem; line-height: 1.62; max-width: 74ch; }

.callout { border-left: 3px solid var(--mml-primary); background: rgba(var(--mml-primary-rgb), .06); padding: var(--sp-lg); border-radius: 0 var(--r-md) var(--r-md) 0; }
.callout--warn { border-left-color: var(--mml-viz-warn); background: rgba(245, 158, 11, .09); }
.callout--info { border-left-color: var(--mml-accent); background: rgba(var(--mml-accent-rgb), .07); }
.callout p:last-child { margin-bottom: 0; }
.callout .k { display: block; font-family: var(--font-mono); font-size: .6rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); margin-bottom: var(--sp-xs); }

.pullquote { font-family: var(--font-serif); font-size: clamp(1.05rem, .98rem + .4vw, 1.3rem); line-height: 1.45; color: var(--mml-text); margin: 0; }
.pullquote b { font-family: var(--font-sans); font-weight: 700; letter-spacing: -.02em; color: var(--mml-viz-danger); }
.pullquote + .src, .src { margin-top: var(--sp-md); font-family: var(--font-mono); font-size: .6rem; letter-spacing: .1em; text-transform: uppercase; color: var(--mml-text-3); }

.notecard { border: 1px solid var(--mml-rule); border-radius: var(--r-lg); padding: .65rem .75rem; }
.notecard + .notecard { margin-top: var(--sp-sm); }
.notecard__k { font-family: var(--font-mono); font-size: .56rem; letter-spacing: .13em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; }
.notecard__v { font-size: 1.02rem; font-weight: 700; letter-spacing: -.02em; margin-top: .1rem; }
.notecard__n { font-size: .74rem; color: var(--mml-text-2); margin: .15rem 0 0; line-height: 1.45; }

/* ═══ DATA-VIZ FRAMES ═════════════════════════════════════════════════════════ */
.vizframe { border: 1px solid var(--mml-border); border-radius: var(--r-xl); background: var(--mml-surface); overflow: hidden; min-width: 0; box-shadow: var(--shadow-sm); }
.vizframe__head { display: flex; flex-wrap: wrap; gap: .35rem var(--sp-lg); align-items: baseline; justify-content: space-between; padding: .8rem 1.05rem; border-bottom: 1px solid var(--mml-rule); background: var(--mml-surface-hover); }
.vizframe__t { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-2); }
.vizframe__key { display: flex; gap: var(--sp-md); flex-wrap: wrap; font-family: var(--font-mono); font-size: .62rem; letter-spacing: .06em; color: var(--mml-text-3); }
.vizframe__key i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: .35rem; vertical-align: -1px; }
.vizframe__body { padding: .4rem .55rem .55rem; }
.vizframe__foot { padding: .6rem 1.05rem .7rem; border-top: 1px solid var(--mml-rule); font-size: .78rem; color: var(--mml-text-3); line-height: 1.5; }
.vizframe svg { width: 100%; height: auto; display: block; }

.scroller { overflow-x: auto; overflow-y: hidden; min-width: 0; max-width: 100%; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--mml-rule-strong) transparent; }
.scroller::-webkit-scrollbar { height: 7px; }
.scroller::-webkit-scrollbar-thumb { background: var(--mml-rule-strong); border-radius: var(--r-pill); }
.scrollhint { display: none; font-family: var(--font-mono); font-size: .6rem; letter-spacing: .12em; text-transform: uppercase; color: var(--mml-text-3); margin-top: var(--sp-sm); align-items: center; gap: .4rem; }
@media (max-width: 900px) { .scrollhint { display: flex; } }

/* AUTOMATIC edge fade — the affordance that does not depend on remembering markup.
   .scrollhint is an explicit sibling element, so it only appears where an author
   added one: 16 of 21 overflowing containers had none, and the worst case clipped 57%
   of the homepage week chart at 390px with nothing to say it could be swiped.
   This is the CSS-only scroll-shadow trick and it is self-managing: two fixed
   background-attachment layers (the white "cover" pads) sit over two scrolling
   `local` layers (the shadows), so each shadow is revealed only while there is more
   content in that direction, and hides itself at the ends. Nothing to wire up, and it
   cannot fall out of sync with the content.
   The gradients use --mml-surface, so a .scroller on a different background needs its
   own --scroller-bg. */
.scroller {
  --scroller-bg: var(--mml-surface);
  background:
    linear-gradient(to right, var(--scroller-bg) 30%, transparent) left center / 34px 100% no-repeat local,
    linear-gradient(to left,  var(--scroller-bg) 30%, transparent) right center / 34px 100% no-repeat local,
    linear-gradient(to right, rgba(var(--mml-shadow-rgb, 0, 0, 0), .16), transparent) left center / 16px 100% no-repeat scroll,
    linear-gradient(to left,  rgba(var(--mml-shadow-rgb, 0, 0, 0), .16), transparent) right center / 16px 100% no-repeat scroll;
}
/* No dark-band override needed: .section--dark already re-points --mml-surface to
   --mml-earth-2, so the pads follow the ground automatically. */

.browserframe { position: relative; min-width: 0; border: 1px solid var(--mml-rule-strong); border-radius: var(--r-xl); overflow: hidden; background: var(--mml-surface); box-shadow: var(--shadow-lg); }
.browserframe__bar { display: flex; align-items: center; gap: .7rem; padding: .55rem .8rem; background: var(--mml-surface-hover); border-bottom: 1px solid var(--mml-rule); }
.browserframe__dots { display: flex; gap: .35rem; }
.browserframe__dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--mml-rule-strong); display: block; }
.browserframe__url { flex: 1; max-width: 340px; font-family: var(--font-mono); font-size: .66rem; color: var(--mml-text-3); background: var(--mml-bg); border: 1px solid var(--mml-rule); border-radius: var(--r-pill); padding: .26rem .7rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.browserframe__chip { margin-left: auto; font-family: var(--font-mono); font-size: .56rem; letter-spacing: .14em; font-weight: 800; color: var(--mml-viz-warn); border: 1px solid var(--mml-viz-warn); border-radius: var(--r-sm); padding: .14rem .42rem; white-space: nowrap; }

/* SVG text drawn straight onto soil. The halo stroke is painted UNDER the glyph so
   the label survives on bone-dry tan and on soaked near-black alike (worst measured
   case 6.06:1). Never set fill on .soilTxt text from the markup. */
.soilTxt text, text.soilTxt {
  fill: var(--mml-soil-ink);
  paint-order: stroke fill;
  stroke: var(--mml-soil-halo); stroke-width: 3.6px; stroke-linejoin: round; stroke-linecap: round;
}
.soilTxt.is-thin text, text.soilTxt.is-thin { stroke-width: 2.6px; }
/* The two accent inks used for on-soil values. Measured over the halo: warm 7.12:1,
   cool 6.06:1 against the worst-case (dry topsoil) background. */
.soilTxt text.is-warm, text.soilTxt.is-warm { fill: var(--mml-soil-ink-warm); }
.soilTxt text.is-cool, text.soilTxt.is-cool { fill: var(--mml-soil-ink-cool); }

/* In-plot chart annotations. Same trick as .soilTxt but the halo is the panel
   colour, so a label stays readable where it crosses a gridline, a threshold
   rule or the series itself. Keeps every annotation at its own token's ratio
   instead of whatever it happens to be sitting on. */
.viznote text { paint-order: stroke fill; stroke: var(--mml-surface); stroke-width: 3.6px; stroke-linejoin: round; stroke-linecap: round; }

.pausebtn {
  display: inline-flex; align-items: center; gap: .42rem;
  font-family: var(--font-mono); font-size: .63rem; letter-spacing: .12em; text-transform: uppercase; font-weight: 700;
  padding: .38rem .7rem; border-radius: var(--r-pill); border: 1px solid var(--mml-rule-strong);
  background: var(--mml-surface); color: var(--mml-text-2); cursor: pointer;
}
.pausebtn:hover { color: var(--mml-text); border-color: var(--mml-link); }
.pausebtn svg { width: 9px; height: 9px; }
.pausebtn .i-play { display: none; }
.pausebtn[aria-pressed="true"] .i-play { display: block; }
.pausebtn[aria-pressed="true"] .i-pause { display: none; }

/* ═══ CALCULATOR CONTROLS ═════════════════════════════════════════════════════ */
.rangefield { display: block; margin-bottom: var(--sp-lg); }
.rangefield__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-md); margin-bottom: .3rem; }
.rangefield__row span { font-size: .85rem; color: var(--mml-text-2); }
.rangefield__out { font-family: var(--font-mono); font-size: .95rem; font-weight: 700; color: var(--mml-text); font-variant-numeric: tabular-nums; }
.rangefield input[type="range"] { width: 100%; accent-color: var(--mml-primary); height: 1.4rem; }
.rangefield .help { margin-top: .15rem; }

/* ═══ MOTION ══════════════════════════════════════════════════════════════════ */
.reveal { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(20px); transition: opacity .7s cubic-bezier(.2,.7,.3,1), transform .7s cubic-bezier(.2,.7,.3,1); }
  .reveal.is-in { opacity: 1; transform: none; }
  .reveal[data-d="1"] { transition-delay: .08s; }
  .reveal[data-d="2"] { transition-delay: .16s; }
  .reveal[data-d="3"] { transition-delay: .24s; }
  .reveal[data-d="4"] { transition-delay: .32s; }

  @keyframes mml-sway { 0%, 100% { transform: skewX(-1deg); } 50% { transform: skewX(1.3deg); } }
  .swaygroup { transform-box: view-box; animation: mml-sway 7s ease-in-out infinite; }
  @keyframes mml-tx { 0% { opacity: 0; transform: scale(.55); } 22% { opacity: .85; } 70%, 100% { opacity: 0; transform: scale(1.5); } }
  .txarc { transform-box: fill-box; transform-origin: 0% 100%; animation: mml-tx 3.2s ease-out infinite; }
  .txarc:nth-of-type(2) { animation-delay: .22s; }
  .txarc:nth-of-type(3) { animation-delay: .44s; }
  @keyframes mml-led { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
  .led { animation: mml-led 3.2s ease-in-out infinite; }
  html.is-paused .swaygroup, html.is-paused .txarc, html.is-paused .led { animation-play-state: paused; }
  @keyframes mml-dash { to { stroke-dashoffset: 0; } }
  .drawin { stroke-dasharray: var(--len, 400); stroke-dashoffset: var(--len, 400); }
  .is-in .drawin { animation: mml-dash 1.5s cubic-bezier(.3,.8,.4,1) forwards; }
  .is-in .drawin.d2 { animation-delay: .22s; }
  .is-in .drawin.d3 { animation-delay: .44s; }
  @keyframes mml-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
  .is-in .growbar { transform-box: fill-box; transform-origin: bottom; animation: mml-grow .8s cubic-bezier(.3,.9,.4,1) both; }
  .fadein { opacity: 0; transition: opacity .55s ease; }
  .is-in .fadein { opacity: 1; }
  .is-in .fadein.d2 { transition-delay: .5s; }
  .is-in .fadein.d3 { transition-delay: .8s; }
  .is-in .fadein.d4 { transition-delay: 1.1s; }
}
@media (prefers-reduced-motion: reduce) {
  .drawin { stroke-dasharray: none; stroke-dashoffset: 0; }
  .fadein { opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   HOMEPAGE-SPECIFIC COMPOSITIONS
   These are the few places the system is bent to fit one page. Everything above
   is reusable; everything below assumes pages/home.php.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ---- Hero (the soil profile) ---- */
.hero {
  position: relative; overflow: hidden;
  background:
    radial-gradient(110% 58% at 74% -12%, rgba(var(--mml-primary-rgb), .13), transparent 62%),
    radial-gradient(80% 46% at 8% -6%, rgba(245, 158, 11, .09), transparent 60%),
    radial-gradient(140% 34% at 50% 96%, rgba(160, 143, 86, .2), transparent 70%),
    linear-gradient(var(--mml-sky-1), var(--mml-sky-2));
}
.hero__inner { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2xl); align-items: start; padding-top: clamp(1.2rem, .9rem + 1.4vw, 2rem); padding-bottom: clamp(.5rem, .3rem + 1vw, 1.2rem); }
@media (min-width: 1000px) {
  .hero__inner { grid-template-columns: minmax(0, 1.42fr) minmax(280px, .58fr); gap: 0 var(--sp-3xl); grid-template-rows: auto 1fr; }
  .hero__copy { grid-row: 1 / span 2; grid-column: 1; }
  .hero__plate { grid-row: 1; grid-column: 2; }
  .hero__log { grid-row: 2; grid-column: 2; margin-top: var(--sp-md); align-self: start; }
}
@media (max-width: 999px) { .hero__plate, .hero__log { max-width: 520px; } }
.hero__title { font-size: clamp(2.05rem, 1.3rem + 2.85vw, 3.5rem); line-height: 1.03; letter-spacing: -.03em; font-weight: 800; margin: 0 0 var(--sp-md); text-wrap: balance; }
.hero__title .l2 { display: block; }
.hero__sub { font-size: clamp(1.02rem, .95rem + .4vw, 1.18rem); color: var(--mml-text-2); max-width: 53ch; line-height: 1.6; margin-bottom: 0; }
.hero__sub b { color: var(--mml-text); font-weight: 650; }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--sp-md); margin: var(--sp-xl) 0 0; }
/* .82rem, not .7rem. This line carries the price, the cancellation promise and the
   three radios — it is the objection-handling line directly under the primary CTA, and
   at 11.2px it was set smaller than a photo caption. Bumped to ~13px and given the
   --mml-text-2 ink so it reads as content rather than fine print. The mono face and
   letter-spacing stay, so it still reads as an instrument label, not a paragraph. */
.hero__note { margin-top: var(--sp-md); color: var(--mml-text-2); font-family: var(--font-mono); font-size: .82rem; letter-spacing: .04em; display: flex; flex-wrap: wrap; gap: .4rem .8rem; align-items: center; }
.hero__note s { text-decoration: none; color: var(--mml-ink-dec); }

.airplate { border: 1px solid var(--mml-rule-strong); border-radius: var(--r-xl); background: rgba(var(--mml-surface-rgb), .72); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); overflow: hidden; box-shadow: var(--shadow-sm); }
.airplate__h { display: flex; align-items: center; gap: .5rem; padding: .55rem .8rem; border-bottom: 1px solid var(--mml-rule); font-family: var(--font-mono); font-size: .64rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); }
.airplate__h svg { width: 15px; height: 15px; color: var(--c-light); }
.airplate ul { list-style: none; margin: 0; padding: .15rem .8rem .5rem; }
.airplate li { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-lg); padding: .42rem 0; border-bottom: 1px dotted var(--mml-rule); font-size: .82rem; color: var(--mml-text-2); }
.airplate li:last-child { border-bottom: 0; }
.airplate b { font-family: var(--font-mono); font-size: .9rem; font-weight: 700; color: var(--mml-text); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.airplate .hi { background: rgba(var(--mml-primary-rgb), .1); margin-inline: -.8rem; padding-inline: .8rem; border-bottom: 0; border-top: 1px solid var(--mml-rule); }
.airplate .hi span, .airplate .hi b { color: var(--mml-link); }
.airplate__f { padding: .45rem .8rem .55rem; border-top: 1px solid var(--mml-rule); font-family: var(--font-mono); font-size: .6rem; letter-spacing: .09em; color: var(--mml-text-3); text-transform: uppercase; display: flex; align-items: center; gap: .4rem; }

.uplog { border: 1px solid var(--mml-rule-strong); border-radius: var(--r-xl); overflow: hidden; background: rgba(var(--mml-surface-rgb), .66); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); box-shadow: var(--shadow-sm); }
.uplog__h { display: flex; align-items: center; justify-content: space-between; gap: .6rem; padding: .5rem .8rem; border-bottom: 1px solid var(--mml-rule); font-family: var(--font-mono); font-size: .61rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); }
.uplog__h em { font-style: normal; color: var(--mml-link); display: inline-flex; align-items: center; gap: .35rem; }
.uplog ol { list-style: none; margin: 0; padding: .3rem .8rem .55rem; font-family: var(--font-mono); font-size: .69rem; color: var(--mml-text-2); font-variant-numeric: tabular-nums; }
.uplog li { display: flex; align-items: center; gap: .65rem; padding: .22rem 0; white-space: nowrap; border-bottom: 1px dotted var(--mml-rule); }
.uplog li:last-child { border-bottom: 0; }
.uplog li i { font-style: normal; color: var(--mml-text-3); width: 3.6em; flex: none; }
.uplog li b { color: var(--mml-text); font-weight: 700; width: 3.6em; text-align: right; }
.uplog li s { text-decoration: none; color: var(--mml-text-3); flex: 1; overflow: hidden; text-overflow: ellipsis; }
.uplog li:first-child b { color: var(--mml-link); }

.ground { position: relative; margin-top: -2.4rem; }
.ground__svg { display: block; width: 100%; height: auto; }
@media (max-width: 1000px) { .ground__svg { height: 400px; } }
@media (max-width: 600px) { .ground__svg { height: 320px; } }
/* Cropped view: the technical labels must still read at ~0.6 scale. */
.ground__svg.is-narrow .a-lbl { font-size: 17px; }
.ground__svg.is-narrow .a-sub { font-size: 14px; }
.ground__svg.is-narrow .a-val { font-size: 40px; }
.ground__svg.is-narrow .rulertxt { font-size: 21px; text-anchor: start; transform: translateX(48px); }

/* ---- The problem plate ---- */
.ledger { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-lg); margin-top: var(--sp-lg); }
@media (min-width: 840px) { .ledger { grid-template-columns: 1.15fr .95fr .9fr; } }
.lcard { border: 1px solid var(--mml-border); border-radius: var(--r-xl); background: var(--mml-surface); padding: var(--sp-lg); display: flex; flex-direction: column; }
.lcard__t { font-family: var(--font-mono); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); margin-bottom: var(--sp-md); }
.lcard .src { margin-top: auto; padding-top: var(--sp-md); border-top: 1px solid var(--mml-rule); }
.arith { font-family: var(--font-mono); font-size: .79rem; line-height: 1.95; color: var(--mml-text-2); font-variant-numeric: tabular-nums; }
.arith div { display: flex; justify-content: space-between; gap: var(--sp-lg); white-space: nowrap; }
.arith div span:last-child { color: var(--mml-text); font-weight: 650; }
.arith .tot { border-top: 1.5px solid var(--mml-text); margin-top: .35rem; padding-top: .35rem; }
.arith .tot span:last-child { color: var(--mml-viz-danger); font-weight: 800; font-size: .98rem; }

/* ---- The app mock ---- */
.appmock { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.appmock__top { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .85rem; padding: .65rem .9rem; border-bottom: 1px solid var(--mml-rule); }
.appmock__dev { display: inline-flex; align-items: center; gap: .5rem; font-size: .83rem; font-weight: 650; color: var(--mml-text); }
/* .appmock__k and .steptrack__k replace <s> where the content is REAL (a device id, a
   step's timing): <s> means retracted, and AT announces it as struck through. <s> is kept
   only for the decorative middot separators, which now carry aria-hidden. The .uplog rule
   below is fine as-is — that whole container is aria-hidden. */
.appmock__dev .appmock__k { text-decoration: none; font-family: var(--font-mono); font-size: .68rem; color: var(--mml-text-3); font-weight: 600; letter-spacing: .05em; }
.appmock__cols { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .appmock__cols { grid-template-columns: 208px minmax(0, 1fr) 244px; } }
.appmock__side { padding: .85rem .9rem; }
@media (min-width: 900px) { .appmock__side { border-right: 1px solid var(--mml-rule); } }
@media (max-width: 899px) { .appmock__side, .appmock__aside { border-top: 1px solid var(--mml-rule); } }
.appmock__aside { padding: .85rem .9rem; }
@media (min-width: 900px) { .appmock__aside { border-left: 1px solid var(--mml-rule); } }
.appmock__main { padding: .85rem .95rem 1rem; min-width: 0; }
.appmock .lbl { font-family: var(--font-mono); font-size: .56rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; margin-bottom: .65rem; }
.ring { display: flex; flex-direction: column; align-items: center; gap: .15rem; margin-bottom: .85rem; }
.ring svg { width: 126px; height: 126px; }
.ring__v { font-size: 2.05rem; font-weight: 800; letter-spacing: -.04em; fill: var(--mml-text); font-family: var(--font-sans); }
.ring__u { font-family: var(--font-mono); font-size: .52rem; letter-spacing: .15em; fill: var(--mml-text-3); font-weight: 700; }
.ring__cap { font-size: .74rem; color: var(--mml-text-2); text-align: center; line-height: 1.35; margin: 0; }
.ring__cap b { color: var(--mml-viz-warn); font-weight: 700; }
.subs { display: flex; flex-direction: column; gap: .48rem; }
.sub__r { display: flex; justify-content: space-between; margin-bottom: .2rem; font-family: var(--font-mono); font-size: .7rem; color: var(--mml-text-2); }
.sub__r b { color: var(--mml-text); font-variant-numeric: tabular-nums; }
.sub__t { height: 4px; border-radius: var(--r-pill); background: var(--mml-surface-hover); overflow: hidden; border: 1px solid var(--mml-rule); }
.sub__f { height: 100%; border-radius: var(--r-pill); background: var(--mml-primary); }
.sub__f.is-warn { background: var(--mml-viz-warn-fill); }
.condlist { list-style: none; margin: 0; padding: 0; font-size: .73rem; color: var(--mml-text-2); }
.condlist li { display: flex; justify-content: space-between; gap: .6rem; padding: .28rem 0; border-bottom: 1px dotted var(--mml-rule); align-items: baseline; }
.condlist li > span { min-width: 0; }
.condlist b { flex: none; }
.condlist li:last-child { border-bottom: 0; }
.condlist b { font-family: var(--font-mono); color: var(--mml-text); font-weight: 700; font-variant-numeric: tabular-nums; }
.advis { border: 1px solid rgba(var(--mml-primary-rgb), .4); border-radius: var(--r-lg); overflow: hidden; background: rgba(var(--mml-primary-rgb), .08); margin-bottom: .8rem; }
.advis__h { padding: .48rem .68rem; font-family: var(--font-mono); font-size: .56rem; letter-spacing: .14em; font-weight: 800; color: var(--mml-link); border-bottom: 1px solid rgba(var(--mml-primary-rgb), .28); display: flex; gap: .4rem; align-items: center; }
.advis__h svg { width: 12px; height: 12px; }
.advis__b { padding: .6rem .68rem .7rem; }
.advis__big { font-size: 1.3rem; font-weight: 800; letter-spacing: -.035em; line-height: 1.1; margin-bottom: .12rem; }
.advis__sm { font-family: var(--font-mono); font-size: .66rem; color: var(--mml-text-2); line-height: 1.62; margin: 0; }
.advis__sm b { color: var(--mml-text); }
.chartbox { position: relative; min-width: 0; height: 272px; }
.chartbox canvas { max-width: 100%; }
.mocktabs { display: flex; border-top: 1px solid var(--mml-rule); overflow-x: auto; scrollbar-width: none; }
.mocktabs::-webkit-scrollbar { display: none; }
.mocktabs span { flex: 1 0 auto; padding: .55rem .75rem; font-family: var(--font-mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 700; color: var(--mml-text-3); border-right: 1px solid var(--mml-rule); white-space: nowrap; text-align: center; }
.mocktabs span:last-child { border-right: 0; }
.mocktabs span.is-on { color: var(--mml-link); box-shadow: inset 0 -2px 0 var(--mml-primary); background: var(--mml-surface-hover); }

/* ---- Calculator ---- */
.calcgrid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-2xl); }
@media (min-width: 900px) { .calcgrid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: var(--sp-3xl); align-items: start; } }
.calcout { border: 1px solid var(--mml-border); border-radius: var(--r-xl); background: var(--mml-surface); padding: var(--sp-xl); }
.calcout__v { font-size: clamp(2.2rem, 1.7rem + 2vw, 3.1rem); font-weight: 800; letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; color: var(--mml-link); }
.calcout__u { font-family: var(--font-mono); font-size: .62rem; letter-spacing: .14em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; display: block; margin-top: var(--sp-xs); }
.calcout__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-lg); margin-bottom: var(--sp-lg); }
.calcbars svg { width: 100%; height: auto; display: block; }
.calcwork { font-family: var(--font-mono); font-size: .74rem; line-height: 1.85; color: var(--mml-text-2); font-variant-numeric: tabular-nums; margin: 0; min-width: 0; }
.calcwork div { display: flex; justify-content: space-between; gap: var(--sp-md); min-width: 0; }
.calcwork div span:first-child { min-width: 0; overflow-wrap: anywhere; }
.calcwork div span:last-child { color: var(--mml-text); font-weight: 650; white-space: nowrap; flex: none; }
.calcwork .tot { border-top: 1.5px solid var(--mml-rule-strong); margin-top: .3rem; padding-top: .3rem; }
/* Prose inside the working-out. NOT a .calcwork div — those are nowrap. */
.calcwork__note { margin: var(--sp-md) 0 0; font-family: var(--font-sans); font-size: .82rem; line-height: 1.55; color: var(--mml-link); white-space: normal; }

/* ---- Pricing preview ---- */
.pricepreview { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-lg); }
@media (min-width: 780px) { .pricepreview { grid-template-columns: 1fr 1fr; } }
.pricepreview .card { display: flex; flex-direction: column; gap: var(--sp-xs); }
.pricepreview .amt { font-size: 2.1rem; font-weight: 800; letter-spacing: -.035em; color: var(--mml-text); }
.pricepreview .per { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--mml-text-3); font-weight: 700; }

/* ═══════════════════════════════════════════════════════════════════════════════
   LEGACY PAGE STYLES — /how-it-works, /features, /tools, /pricing, /faq, auth.
   Owned by other pages; left intact.
   ═══════════════════════════════════════════════════════════════════════════════ */
.legal h1 { margin-bottom: var(--sp-xs); }
.legal h2 { margin-top: var(--sp-2xl); }
.legal ul { padding-left: var(--sp-xl); }
.legal li { margin-bottom: var(--sp-xs); }

.section .card { box-shadow: var(--shadow-sm); }
.grid-cards .card, .tools-grid .card, .pricing .card {
  transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.grid-cards .card:hover, .tools-grid .card:hover, .pricing .card:hover {
  transform: translateY(-3px);
  border-color: rgba(var(--mml-primary-rgb), .4);
  box-shadow: var(--shadow-md), 0 0 0 3px rgba(var(--mml-primary-rgb), .06);
}

.value-prop { text-align: center; }
.value-prop__icon, .feature__icon {
  display: inline-grid; place-content: center;
  width: 52px; height: 52px; border-radius: var(--r-xl);
  background: var(--mml-primary-50); color: var(--mml-link);
  font-size: 1.4rem; margin-bottom: var(--sp-md);
}
.tools-teaser .card { text-align: center; }
.tools-teaser .card i {
  display: inline-grid; place-content: center;
  width: 46px; height: 46px; border-radius: var(--r-lg);
  background: var(--mml-accent-50); color: var(--mml-accent);
  font-size: 1.25rem; margin-bottom: var(--sp-md);
}
.tools-teaser h4 { margin-bottom: var(--sp-xs); }
.feature { display: flex; flex-direction: column; }

.tools-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: var(--sp-lg); }
.tool-card__head { display: flex; align-items: center; gap: var(--sp-md); margin-bottom: var(--sp-sm); }
.tool-card__head i { font-size: 1.3rem; color: var(--mml-primary); transition: transform .2s ease; }
.tool-card:hover .tool-card__head i { transform: scale(1.12) rotate(-4deg); }
.tool-card__head h3 { margin: 0; }

.steps { list-style: none; margin: 0 0 var(--sp-3xl); padding: 0; display: grid; gap: var(--sp-lg); }
.step { display: flex; gap: var(--sp-lg); align-items: flex-start; }
.step__num {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 50%; display: grid; place-content: center;
  background: linear-gradient(135deg, var(--mml-primary), var(--mml-primary-dark));
  color: #fff; font-weight: 700; box-shadow: var(--shadow-xs);
}
.how-transports { margin-top: var(--sp-3xl); }
.how-transports .card i { font-size: 1.35rem; color: var(--mml-accent); margin-bottom: var(--sp-sm); }

.cta-band {
  background-image:
    var(--mml-pattern-leaf),
    linear-gradient(115deg, var(--mml-primary-50), rgba(var(--mml-accent-rgb), .05));
  border-top: 1px solid var(--mml-border); border-bottom: 1px solid var(--mml-border);
}
.cta-band__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-lg); flex-wrap: wrap; }
.cta-band h2 { margin-bottom: var(--sp-xs); }

/* .pagehero__actions is listed alongside .hero__cta everywhere below: the sub-page
   masthead buttons have to lift, glow and settle exactly like the homepage's, or the
   two mastheads still read as two different hands. */
.hero__cta .btn, .pagehero__actions .btn, .section__cta .btn, .cta-band__inner .btn {
  transition: background .15s ease, border-color .15s ease, transform .18s ease, box-shadow .18s ease;
}
.hero__cta .btn-primary, .pagehero__actions .btn-primary, .section__cta .btn-primary, .cta-band__inner .btn-primary { box-shadow: var(--shadow-primary); }
.hero__cta .btn-ghost, .pagehero__actions .btn-ghost { background: var(--mml-surface); }
.hero__cta .btn:hover, .pagehero__actions .btn:hover, .section__cta .btn:hover, .cta-band__inner .btn:hover { transform: translateY(-2px); }
.hero__cta .btn-primary:hover, .pagehero__actions .btn-primary:hover, .section__cta .btn-primary:hover, .cta-band__inner .btn-primary:hover { box-shadow: var(--shadow-primary), var(--shadow-md); }
.hero__cta .btn-ghost:hover, .pagehero__actions .btn-ghost:hover { box-shadow: var(--shadow-sm); }
.hero__cta .btn:active, .pagehero__actions .btn:active, .section__cta .btn:active, .cta-band__inner .btn:active { transform: translateY(0); }

/* /features + /tools + /how-it-works keep the old hero art; /home no longer uses it. */
.hero__art { position: relative; display: flex; justify-content: center; }
.hero__art::before {
  content: ""; position: absolute; inset: -8% -6%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(var(--mml-primary-rgb), .16), transparent 72%);
}
.ring-demo {
  position: relative;
  background: var(--mml-surface); border: 1px solid var(--mml-border);
  border-radius: var(--r-xl); box-shadow: var(--shadow-lg);
  padding: var(--sp-2xl); display: flex; gap: var(--sp-xl); align-items: center;
}
.ring-demo__ring {
  width: 120px; height: 120px; border-radius: 50%; display: grid; place-content: center; text-align: center;
  background: conic-gradient(var(--mml-success) 331deg, var(--mml-border) 0deg);
  position: relative;
}
.ring-demo__ring::before { content: ""; position: absolute; inset: 10px; background: var(--mml-surface); border-radius: 50%; }
.ring-demo__score { position: relative; font-size: 2rem; font-weight: 700; color: var(--mml-text); }
.ring-demo__label { position: relative; font-size: .7rem; color: var(--mml-text-2); display: block; }
.ring-demo__stats { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-sm); font-size: .85rem; }
.ring-demo__stats li { display: flex; gap: var(--sp-sm); align-items: center; }

/* ---- Pricing ---- */
.pricing { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-lg); max-width: 720px; margin: 0 auto var(--sp-2xl); }
.pricing__card { text-align: center; position: relative; }
.pricing__card--featured {
  border-color: rgba(var(--mml-primary-rgb), .55);
  background-image: linear-gradient(180deg, var(--mml-primary-50), var(--mml-surface) 55%);
  box-shadow: var(--shadow-md), 0 0 0 4px rgba(var(--mml-primary-rgb), .08);
}
.pricing .pricing__card--featured:hover {
  border-color: rgba(var(--mml-primary-rgb), .7);
  box-shadow: var(--shadow-lg), 0 0 0 4px rgba(var(--mml-primary-rgb), .1);
}
@media (min-width: 861px) {
  .pricing__card--featured { transform: translateY(-6px); }
  .pricing .pricing__card--featured:hover { transform: translateY(-9px); }
}
.pricing__tag { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); box-shadow: var(--shadow-sm); }
.pricing__name { margin-bottom: var(--sp-sm); }
.pricing__price { margin: var(--sp-sm) 0; }
.pricing__amount { font-size: 2.2rem; font-weight: 700; color: var(--mml-text); }
.pricing__card--featured .pricing__amount { color: var(--mml-heading-accent); }
.pricing__per { color: var(--mml-text-2); font-size: .85rem; }
.pricing__included { max-width: 720px; margin: 0 auto; }
.checklist { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-sm); }
.checklist li { display: flex; gap: var(--sp-sm); align-items: flex-start; font-size: .9rem; }
.checklist i { color: var(--mml-success); margin-top: 2px; }
.pricing__faq { max-width: 720px; margin: var(--sp-2xl) auto 0; }

/* ---- FAQ ---- */
.faq-list { display: grid; gap: var(--sp-md); }
.faq-item { transition: border-color .2s ease; }
.faq-item summary { cursor: pointer; font-weight: 600; }
.faq-item summary:hover { color: var(--mml-link); }
.faq-item[open] { border-color: rgba(var(--mml-primary-rgb), .4); }
.faq-item[open] summary { color: var(--mml-link); margin-bottom: var(--sp-sm); }

/* ---- Auth ---- */
.auth { display: flex; justify-content: center; }
.auth__card { width: 100%; max-width: 420px; box-shadow: var(--shadow-md); }
.auth__title { margin-bottom: var(--sp-xs); }
.auth__links { margin-top: var(--sp-lg); text-align: center; display: flex; gap: var(--sp-sm); justify-content: center; flex-wrap: wrap; }
.field--check label { display: flex; gap: var(--sp-sm); align-items: center; font-weight: 400; }
.form-banner { margin-bottom: var(--sp-lg); }
.btn .is-loading, .btn.is-loading { opacity: .7; }

/* ═══ FOOTER ══════════════════════════════════════════════════════════════════
   The earth band, so every marketing page lands on the same ground the homepage
   opens with. Ink is re-pointed the same way .section--dark does it. */
.site-footer {
  --mml-text: var(--mml-cream);
  --mml-text-2: var(--mml-cream-2);
  --mml-text-3: var(--mml-cream-3);
  --mml-rule: rgba(var(--mml-cream-rgb), .16);
  --mml-border: rgba(var(--mml-cream-rgb), .16);
  --mml-link: var(--mml-primary-light);
  position: relative;
  background: var(--mml-earth-2); color: var(--mml-cream);
  border-top: 1px solid var(--mml-border);
  margin-top: var(--section-pad); padding-top: var(--sp-3xl);
}
.site-footer::before {
  content: ""; position: absolute; top: -1px; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(var(--mml-primary-rgb), .55), transparent);
}
/* When the page already closes on the earth band, the footer's breathing margin
   shows as a white stripe between two dark blocks. Butt them together instead.
   Falls back to the margin where :has() is unsupported, which is merely a gap. */
main:has(> .section--dark:last-child) + .site-footer { margin-top: 0; border-top-color: rgba(var(--mml-cream-rgb), .1); }
.site-footer .brand { color: var(--mml-cream); }
.site-footer .brand__mark { color: var(--mml-primary-light); }
.site-footer .muted { color: var(--mml-cream-2); }
.site-footer__inner { display: flex; justify-content: space-between; gap: var(--sp-2xl); flex-wrap: wrap; padding-bottom: var(--sp-2xl); }
.site-footer__brand { max-width: 300px; }
.site-footer .brand__name { font-size: 1.05rem; }
.site-footer svg.brand__mark { width: 24px; height: 24px; }
.site-footer__brand p { margin-top: var(--sp-sm); }
.site-footer__cols { display: flex; gap: var(--sp-3xl); flex-wrap: wrap; }
/* h2, not h4: these are the top-level headings inside the footer landmark and
   the last heading before them is the closing section h2 — h4 skipped a rank. */
.footer-col h2 { font-size: .68rem; font-family: var(--font-mono); text-transform: uppercase; letter-spacing: .14em; color: var(--mml-cream-3); margin-bottom: var(--sp-md); }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-sm); }
.footer-col a { color: var(--mml-cream-2); font-size: .88rem; transition: color .15s ease; }
.footer-col a:hover { color: var(--mml-cream); text-decoration: none; }
.site-footer__method { border-top: 1px solid var(--mml-rule); padding-top: var(--sp-lg); padding-bottom: var(--sp-lg); }
.site-footer__method .hairgrid { border-top: 0; }
.site-footer__method .hairgrid > * { border-bottom: 0; padding-block: var(--sp-sm); }
.site-footer__legal { border-top: 1px solid var(--mml-rule); padding-top: var(--sp-md); padding-bottom: var(--sp-lg); color: var(--mml-cream-3); }
.site-footer__legal a { color: var(--mml-cream-2); }
.site-footer__legal a:hover { color: var(--mml-cream); }

/* ═══ RESPONSIVE ══════════════════════════════════════════════════════════════ */
@media (max-width: 860px) {
  .hero__art { order: -1; }
  .checklist { grid-template-columns: 1fr; }
  .site-nav { margin-left: 0; }
  .nav-toggle { display: inline-flex; }
  .nav-menu {
    position: absolute; left: 0; right: 0; top: 100%; flex-direction: column; gap: 0;
    background: var(--mml-surface); border-bottom: 1px solid var(--mml-border);
    padding: var(--sp-sm) var(--sp-lg) var(--sp-md);
    box-shadow: var(--shadow-md);
    display: none;
  }
  .nav-menu.is-open { display: flex; }
  .nav-menu li + li { border-top: 1px solid var(--mml-border); }
  .nav-menu a { display: block; padding: .7rem 2px; }
  .nav-menu a::after { display: none; }
  /* Keep the whole bar on ONE row: brand … [theme] [Sign up] [hamburger].
     Letting it wrap put the actions on a second line and cost 90px of a 390px
     screen's first paint. .nav-menu is position:absolute, so it is unaffected. */
  .site-header__inner { flex-wrap: nowrap; gap: var(--sp-sm); }
  /* nowrap gives the row an intrinsic minimum. The brand is the only elastic part,
     so it must be allowed to shrink or the whole document scrolls sideways. */
  .brand { min-width: 0; flex: 0 1 auto; }
  .brand__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .site-nav { order: 3; margin-left: 0; flex: none; }
  .site-header__actions { order: 2; margin-left: auto; flex: none; }
  .site-footer__cols { gap: var(--sp-2xl); }
}
@media (max-width: 560px) {
  .site-header__actions .nav-login { display: none; }
  .calcout__pair { grid-template-columns: 1fr; }
  /* Full-bleed stacked CTAs read as targets; content-width ones read as ragged. */
  .hero__cta { flex-direction: column; align-items: stretch; }
  .hero__cta .btn { width: 100%; }
}
@media (max-width: 430px) {
  .brand__name { font-size: .95rem; }
  .site-header__inner { gap: var(--sp-xs); }
  .site-header .btn { padding: .45rem .6rem; font-size: .8rem; }
  .theme-toggle { padding: .45rem .5rem; }
}
