/* ============================================================================
   front-door.css — bylineAL umbrella landing (index.html)

   The front door's own sections only. Every colour, typeface and shape token
   comes from suite.css, which this sheet loads after. Nothing here re-declares
   a token that sheet already owns.

   Until 2026-07-27 this lived as ~350 lines of inline <style> in index.html
   plus a second <style id="detell"> block that overrode the first. Sixteen
   selectors were defined in both places and fifteen disagreed: --mark was a
   different colour under the same name, --col was 72rem against 58rem, and the
   retired cream palette was still live underneath a grey one. The page had been
   patched over rather than migrated. Design review 2026-07-27, finding 23.

   Three house laws were being broken here and are repaired:
     - the 3px amber accent rail down the left of .demo .diaghead, retired
       suite-wide at DESIGN-SYSTEM.md:89 — now a rule line above it instead.
       (Written in prose deliberately: spelling the declaration out here put the
       banned pattern's own signature back into the file, and the design detector
       flagged the comment describing the fix as if it were the defect.);
     - two 54px drop shadows on .demo and .proof, against suite.css's own
       stated thesis that rule lines and type do the structural work;
     - Fraunces optical-size and SOFT axes on a font that has neither.

   Local tokens are prefixed --fd- so they can never collide with a system
   token. If a value here needs to be shared, promote it into suite.css rather
   than widening this prefix.
   ============================================================================ */

:root {
  /* NINE TEXT SIZES for the whole product, replacing fifteen. Eight of them
     applied 2026-08-10 from the styling preview; the ninth added 2026-08-12 on
     Ritu's ruling. This is the LAST step to touch, because it is the only one
     that can change where a word breaks.

     The fifteen fractional sizes had one cause and it was not a second scale:
     the root font is 18px and sizes were written in rem, so 0.7rem is 12.6px.

     THE NINTH SIZE CLOSES THE ONE BROKEN STEP. The scale used to run 40px
     straight to 68px, a jump of 1.7 where every other step is 1.2 to 1.45.
     40 to 48 is 1.20 and 48 to 68 is 1.42. It cost no renaming: --t-8 held 68
     and not one declaration in the product used it, so 48 took that name. 48 is
     not an invented number either. It is where the front door's headline stops
     growing, 2.6rem or 46.8px, which was the one headline end that landed on
     nothing.

     A HEADLINE IS NOT A SIZE HERE. It is a ramp that grows with the window, and
     it stays one: h1 keeps its clamp, and only the two ENDS of that clamp read
     tokens. Freezing a headline onto a fixed step is what turned eight of them
     from one line into two when this was measured on 2026-08-10. See
     --track-hero below, and the hero step in preview/build-precision.mjs. */
  --t-1:         12px;
  --t-2:         14px;
  --t-3:         16px;
  --t-4:         19px;
  --t-5:         23px;
  --t-6:         28px;
  --t-7:         40px;
  --t-8:         48px;
  --t-9:         68px;
  /* SEVEN SPACING STEPS for the whole product, replacing thirteen. Applied
     2026-08-10 from the styling preview.

     Values under 4px are left alone: below the base step there is no step to
     round to, and a 1px nudge is usually doing optical work a scale should not
     overrule.

     INLINE padding and margin are only ever REDUCED, never raised. Raising them
     narrows the column the text is set in, and a narrower column is how a
     paragraph gains a line. Measured: rounding to nearest added a line to five
     paragraphs on corporate and social at 390. See inlineAt() in
     preview/build-precision.mjs for which positions of a shorthand count as
     inline. */
  --s-1:         4px;
  --s-2:         8px;
  --s-3:         16px;
  --s-4:         24px;
  --s-5:         40px;
  --s-6:         64px;
  --s-7:         104px;
  /* The x-height match for the mono-to-sans move. MEASURED, not guessed:
     JetBrains Mono renders an x-height of 0.55 em and Schibsted Grotesk 0.527,
     so giving the sans the mono's ratio scales it up about 4.3% and a 12px
     label renders at 12.52px with the two faces sitting on one x-height. See
     preview/x-height.json.

     A number and not the from-font keyword: the number is written down, it can
     be checked against that file, and it does not change silently when a font
     file is updated. */
  --x-adjust:    0.55;
  /* TWO TRACKING VALUES for the whole product, replacing ten. Applied
     2026-08-10 from the styling preview.

     --track-caps is for text the sheet also sets in uppercase. Capitals need
     the air; a sentence does not, which is why positive tracking on mixed-case
     text goes to plain normal here rather than to 0.16em. That would be grotesque
     on a sentence, and 26 selectors were carrying it.

     --track-tight is the only negative value. h1 keeps its own: loosening
     DeskTriage's and FieldReportage's headline from -0.03em to -0.01em wrapped
     both onto two lines, and the line count wins.

     NOT DONE HERE: the trailing letter-space. CSS puts the tracking after the
     LAST character too, so a centred or right-aligned capped label sits half a
     tracking left of where it should. Cancelling it means adding a negative
     margin to 160 rules, which is a second decision and gets measured on its
     own. */
  --track-tight: -0.01em;
  --track-caps:  0.16em;
  /* ONE TRACKING VALUE FOR EVERY HEADLINE. Applied 2026-08-12.

     The product carried four: -0.03em on the tool pages, -0.03em on editorial
     and corporate, -0.025em on the front door, -0.02em on social. This is the
     TIGHTEST of them, and tightest is the safe direction: loosening
     DeskTriage's and FieldReportage's headline from -0.03em to -0.01em wrapped
     both onto two lines when the tracking step was measured on 2026-08-10.
     Tightening cannot add a line.

     It is separate from --track-tight because that is the body's value,
     -0.01em, and a 68px headline and a 16px label do not want the same one. */
  --track-hero:  -0.03em;
  /* ONE RULE WEIGHT for the whole product: every divider in the five sheets
     reads this token instead of carrying its own number.

     THE VALUE IS 1px, AND 0.5px WAS TRIED FIRST AND MEASURED. In Chrome a
     0.5px border occupies exactly the same space as a 1px one and reports as
     1px, at BOTH display densities: a 40px-tall box with 0.5px borders and one
     with 1px borders both measure 42px. Ritu's ruling of 2026-08-10 is that
     Chrome is the only engine in scope, so a half-pixel here is a number that
     looks like a decision and paints like nothing. It would also halve every
     divider on the day some future Chrome starts honouring it, with nobody
     deciding that.

     The point of the token is that the next person changes ONE number, not 141.
     Guard: tests/test_css_architecture.py::HairlineTokenTest. */
  --hairline:    1px;
  /* The front door runs wider than a suite home: its hero is a two-column
     grid carrying a demo panel, where editorial.html and corporate/ are a
     single reading column. Deliberately a DIFFERENT NAME, not a different
     value for --col, so the two can never silently diverge again.

     2026-08-03: --fd-col was the front door's own column and is now the product
     frame (spec §5A: the front door is the standard, so its value became
     everyone's). Kept as an alias because .wrap still reads it. */
  --fd-col:        var(--frame);
  --fd-navy-lift:  #0c3a66;          /* hover lift on the anchored CTA only */
  --section:       clamp(3.5rem, 7vw, 6rem);
}

/* suite.css sets text-decoration per component and carries no bare anchor rule,
   so this has to stay. Every link on this page is chrome, nav or a call to
   action; there are no inline prose links that would lose their affordance. */
a { color: inherit; text-decoration: none; }

/* Small-label floor, matching Social. Fifteen label classes on this page rendered
   below 11px on a phone, down to 9.15px on the "Popular" badge and 9.48px on
   "per seat / mo". The design review raised this for Social (finding 18) and did
   not check the front door, which had the same floor problem. Anything under
   0.70rem is lifted to it: 11.44px at 390, 12.6px at 1440. */

/* Finding 21, the rest of it. The masthead and footer links were given the touch
   floor in the first pass; these two were missed and still measured under it at
   390px: the wordmark at 36px (its image is clamp(36px,4vw,48px), so the link is
   only as tall as the mark on a phone) and .typeset, which carries the four
   pricing actions, at 29.5px. */
a.logo { display: inline-flex; align-items: center; min-height: var(--touch-min); }
.typeset { min-height: var(--touch-min); }

/* The ring and the skip link come from suite.css, which this sheet loads after.
   Only the front door's own focusable chrome needs a floor here.

   Ritu's ruling, 2026-07-28: 44px is the floor for real CONTROLS; inline and
   footer text links take 24px, which is the actual AA target size (2.5.8) and
   exempts inline links besides. Finding 21 had put the full 44px on both, and on
   a phone that is what made the footer 1,444px tall: 17 text links each holding
   open a 44px box. Measured at 390px, the four link columns alone were 865px.
   --touch-link is declared beside --touch-min so the two floors stay legible as
   a pair rather than one being a magic number. */
nav.top a.navlink,
.foot .links a { display: inline-flex; align-items: center; min-height: var(--touch-link); }

/* ============================================================
     The front door's own sections.

     Cool grey-green ground, deep ink, teal accent, navy as a sparing
     deep accent. Rule lines and type carry the structure. One anchored
     solid CTA per zone, everything else typeset. The logo is the fixed
     nib asset and is never re-typeset.

     The three lines above said "cream paper, deep ink" until 2026-07-27.
     They survived the migration out of index.html's inline <style> and
     described a palette retired on 2026-07-14, which is the same
     stale-comment class the design review found in suite.css. Caught by
     reading the file rather than by any gate; see ENGINEERING-PROTOCOL
     section 10.
     ============================================================ */

  .wrap{width:var(--fd-col);margin:0 auto;}

  /* ---- masthead — full-bleed chrome (DeskBrief placement + size) ---- */
  /* Full-bleed chrome, contents on the content column. --fd-col caps at 72rem
     and then centres, while a fixed --gutter does not, so above ~1230px the
     wordmark drifted outside the column everything else aligns to: measured
     0px at 1280, 20px at 1440, 100px at 1600, 200px at 1800. Deriving the
     inline padding from --fd-col locks the two together and collapses to
     exactly --gutter below the cap. 2026-07-28. */
  .masthead{display:flex;align-items:center;justify-content:space-between;gap: var(--s-4);
    flex-wrap:wrap;padding:1.5rem calc((100% - var(--frame)) / 2) 1rem;border-bottom:1px solid var(--rule);}
  .masthead .brandcluster{display:flex;align-items:center;gap: var(--s-3);}
  .masthead .logo{display:inline-flex;align-items:center;line-height:1;}
  /* Optical alignment, 2026-07-28. The nib artwork carries ~1px of internal
     padding at phone scale, so although the image BOX starts on the gutter
     like everything else, the mark's first ink landed 1px inside it. Measured
     off the rendered pixels on DeskCopyPro at 360px: nib 21.0px, the theme
     capsule / eyebrow / h1 all 20.0px, and the delta held at every sampling
     threshold from 40 down to 2, so it is the artwork and not anti-aliasing.
     Ritu: "the wordmark logo sticks out a tad". Corrected in CSS; the SVG is
     a fixed asset and is never edited. */
  .masthead .logo img{margin-left:-1px;display:block;height:clamp(36px,4vw,48px);width:auto;}
  .masthead .descriptor{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);font-weight:500;
    letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--ink-soft);line-height: calc(var(--s-1) * 4);
    padding-left: var(--s-3);border-left:1px solid var(--rule);white-space:nowrap;}
  nav.top{display:flex;align-items:center;gap: var(--s-4);flex-wrap:wrap;}
  nav.top a.navlink{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);
    text-transform:uppercase;color:var(--quiet);transition:color .18s ease;}
  nav.top a.navlink:hover{color:var(--ink);}

  /* ---- anchored CTA (one solid per zone) ---- */
  .cta{display:inline-flex;align-items:center;gap: var(--s-2);font-family: var(--font-display); font-size-adjust: var(--x-adjust);
    font-weight:500;font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;
    background:var(--accent-deep);color:var(--paper);padding: var(--s-3) var(--s-3);border:1px solid var(--accent-deep);
    border-radius:var(--pill);
    /* The mark follows this button's own label. Drawn in --accent it measured
       2.04:1 on this navy, and 1.63:1 on the hover lift. 2026-08-05. */
    --ico-color:currentColor;
    transition:background .18s ease,border-color .18s ease;cursor:pointer;}
  .cta:hover{background:var(--fd-navy-lift);border-color:var(--fd-navy-lift);}
  .cta.lg{font-size: var(--t-2);padding: var(--s-3) var(--s-4);}
  /* .inverse is an OUTLINE button — transparent ground, so the mark keeps the
     accent default and must not inherit the navy label colour. */
  .cta.inverse{background:transparent;color:var(--accent-deep);border-color:var(--accent-deep);--ico-color:var(--accent);}
  .cta.inverse:hover{background:var(--accent-deep);color:var(--paper);--ico-color:currentColor;}
  /* typeset secondary action — hairline underline */
  .typeset{display:inline-flex;align-items:baseline;gap: var(--s-2);font-family:var(--font-display);
    font-variation-settings:"wght" 500;font-size: var(--t-4);color:var(--ink);
    border-bottom:1px solid var(--ink);padding-bottom:.18rem;transition:color .2s ease,border-color .2s ease;}
  .typeset:hover{color:var(--accent);border-bottom-color:var(--accent);}
  .typeset .gl{transition:transform .26s cubic-bezier(.22,.8,.2,1);}
  .typeset:hover .gl{transform:translateX(5px);}

  /* ---- type atoms ---- */
  /* .eyebrow sits on both <p> and <h2> — "Why us?" is a section heading that
     was marked up as a paragraph, which made the page skip h1 -> h3. No reset
     rule is needed: .eyebrow's own font-size, weight and margin already beat
     the UA heading defaults. An h2.eyebrow{font-size:inherit} added here on
     2026-07-27 did the opposite of its intent, inheriting the section's 18px
     so that one eyebrow rendered at 18px against every other one's 12.6px. */
  .eyebrow{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);
    text-transform:uppercase;color:var(--accent);font-weight:500;margin: 0 0 var(--s-3);}
  .eyebrow.muted{color:var(--quiet);}
  
  .rule-top{border-top:2px solid var(--accent-deep);}

  /* ---- four-suite family rail ---- */
  .family{margin-top: var(--s-4);border-top: var(--hairline) solid var(--rule-soft);border-bottom: var(--hairline) solid var(--rule-soft);
    display:grid;grid-template-columns:repeat(4,1fr);}
  /* Status sits ON the name's line, not under it. Ritu, 2026-08-02, after
     Editorial's beta came off: "look at the acres of blank space." The rail was
     a COLUMN — name, then a boxed chip on a second line — and the grid row takes
     its height from the tallest cell, so the one suite without a chip held open
     an empty line while three siblings filled theirs. Moving the status onto the
     baseline means no cell has a second line and no cell can leave a hole,
     whatever its status. */
  .family .fam{padding: var(--s-3) var(--s-3);border-right: var(--hairline) solid var(--rule-soft);display:flex;
    flex-direction:row;align-items:baseline;flex-wrap:wrap;gap: .1rem var(--s-2);}
  .family .fam:first-child{padding-left:0;}
  .family .fam:last-child{border-right:0;}
  .fam .name{font-family:var(--font-display);font-variation-settings:"wght" 560;
    font-size: var(--t-4);letter-spacing: var(--track-tight);color:var(--ink);line-height: calc(var(--s-1) * 5);}
  .fam.soon .name{color:var(--quiet);}
  .fam .name .a{color:var(--accent);font-variation-settings:"wght" 400;}
  /* "a very small iteration in all the boxes" (his words). The bordered chip
     was a boxed control's worth of weight for one status word, sitting next to
     a 1.12rem name; unboxed and smaller, the status reads as an annotation on
     the name, which is what it is. Colour alone carries live/soon, so the word
     stays legible without a frame around it. */
  .fam .state{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);
    text-transform:uppercase;width:max-content;color:var(--quiet);
    font-variation-settings:"wght" 500;}
  .fam.live .state{color:var(--good);}
  a.fam{cursor:pointer;}
  a.fam:hover{background:var(--paper-deep);}
  a.fam.linked:hover .name{color:var(--accent);}

  /* ---- hero ---- */
  .hero{padding-top:var(--section);display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr);
    gap:clamp(2rem,4vw,3.5rem);align-items:start;}
  h1.display{font-family:var(--font-display);font-variation-settings:"wght" 460;
    font-size: clamp(var(--t-5), 1.83vw + 1.133rem, var(--t-8));line-height:1.06;letter-spacing: var(--track-hero);margin:0;color:var(--ink);text-wrap:balance;}
  h1.display br.brk{display:inline;}
  h1.display .you{display:block;color:var(--accent);font-variation-settings:"wght" 400;white-space:nowrap;}
  h1.display .tw{color:var(--accent);font-variation-settings:"wght" 400;white-space:nowrap;}
  /* CSS math needs whitespace on BOTH sides of + and -. Written as ".6vw+.95rem"
     this clamp was invalid, the declaration was dropped, and the lede silently
     fell back. The same typo in html,body pinned the whole page's rem base to
     16px, so every rem size on the front door was 12.5% under its authored
     value. Guarded by tests/test_css_math.py. */
  .hero .lede{font-size: var(--t-5);line-height: calc(var(--s-1) * 9);color:var(--ink-soft);max-width:42ch;margin: var(--s-4) 0 0;text-wrap:pretty;}
  .hero .lede strong{font-family:var(--font-display);font-variation-settings:"wght" 560;font-weight:normal;}
  .hero .actions{display:flex;gap: var(--s-4);align-items:baseline;margin-top: var(--s-5);flex-wrap:wrap;}

  /* ---- DeskCopy Pro animated demo ---- */
  .demo{border: var(--hairline) solid var(--rule-soft);background:var(--paper-warm);}
  .demo .bar{display:flex;align-items:center;padding: var(--s-3) var(--s-3);border-bottom: var(--hairline) solid var(--rule-soft);background:var(--paper-deep);}
  .demo .bar .t{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);}
  .demo .pane{padding: var(--s-4) var(--s-3);}
  .demo .ctrls{display:flex;align-items:center;gap: var(--s-2);flex-wrap:wrap;}
  .demo .ctrls + .ctrls{margin-top: var(--s-2);}
  .demo .lab{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);}
  .demo .ctrl{display:inline-flex;align-items:center;gap: var(--s-2);justify-content:space-between;
    padding: var(--s-2) var(--s-2);font-family:var(--font-body);font-size: var(--t-3);color:var(--ink);
    background:var(--paper);border:1px solid var(--accent-deep);transition:box-shadow .2s ease,border-color .2s ease;}
  .demo .ctrl .caret{color:var(--quiet);}
  .demo .ctrl.on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent);}
  .demo .ctrl.mode{min-width:9.5rem;}
  .demo .chip{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;
    padding: var(--s-2) var(--s-2);border:1px solid var(--rule);background:var(--paper);color:var(--quiet);transition:all .2s ease;}
  .demo .chip.on{border-color:var(--accent-deep);background:var(--accent-deep);color:var(--paper);}
  /* No fixed floor: the reserve is computed from the tallest step at runtime
     (see index.html). A hard-coded one only fought it. */
  .demo .stage{margin-top: var(--s-4);}
  .demo .stage .cap{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent);margin: 0 0 var(--s-3);}
  .demo .row{display:flex;align-items:center;gap: var(--s-2);padding: var(--s-2) 0;border-top: var(--hairline) solid var(--rule-soft);font-family:var(--font-body);font-size: var(--t-4);color:var(--ink);}
  .demo .row:first-of-type{border-top:0;}
  /* The output step. Body serif at reading size, because the point of it is that
     this is prose the desk wrote, not another control being demonstrated. */
  /* The headline the desk wrote. Display face, real headline weight, sized to
     the panel rather than to the page so it cannot outshout h1.display beside it. */
  .demo .wrote-head{font-family:var(--font-display);font-variation-settings:"wght" 620;
    font-size: var(--t-4);line-height: calc(var(--s-1) * 6);letter-spacing: var(--track-tight);color:var(--ink);
    margin: 0 0 var(--s-2);max-width:30ch;text-wrap:balance;}
  .demo .wrote{font-family:var(--font-body);font-size: var(--t-3);line-height: calc(var(--s-1) * 6);
    color:var(--ink);margin: 0 0 var(--s-2);max-width:52ch;}
  .demo .wrote:last-child{margin-bottom:0;}
  /* Ritu's 2026-07-26 ruling: a page showing a conjured story must say it is
     invented, or it presents fiction as news. */
  /* Sits under the prose as a footnote, not above it as a banner: the reader
     should meet the writing first and the provenance second. Ritu's 2026-07-26
     ruling only requires the page to SAY the story is invented. */
  .demo .conjured{display:block;margin: var(--s-3) 0 0;padding-top: var(--s-2);
    border-top: var(--hairline) solid var(--rule-soft);
    font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: normal;
    text-transform:none;color:var(--quiet);}
  .demo .row .m{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-2);}
  .demo .row .ok{color:var(--good);} .demo .row .warn{color:var(--mark);}
  .demo .note{font-style:italic;font-variation-settings:"opsz" 20, "wght" 440, "ital" 1;font-size: var(--t-4);line-height: calc(var(--s-1) * 8);color:var(--ink-soft);margin:0;max-width:42ch;}
  .demo .diaghead{display:flex;align-items:center;justify-content:space-between;padding: var(--s-2) var(--s-2);border-top: var(--hairline) solid var(--mark);background:var(--paper);margin-bottom: var(--s-3);}
  .demo .diaghead .l{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--ink);}
  .demo .diaghead .s{font-family:var(--font-display);font-variation-settings:"wght" 600;font-size: var(--t-4);color:var(--ink);}
  .demo .foot{border-top: var(--hairline) solid var(--rule-soft);padding: var(--s-2) var(--s-3);display:flex;align-items:center;justify-content:space-between;}
  .demo .foot .slug{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent-deep);}
  .demo .foot .dots{display:flex;gap: var(--s-1);}
  .demo .foot .dots i{width:.4rem;height:.4rem;background:var(--rule);transition:background .3s ease;}
  .demo .foot .dots i.on{background:var(--accent);}

  /* ---- rotating hero: tabs + panels ---- */
  .family .fam{cursor:pointer;outline:none;transition:color .18s ease;}
  .family .fam:hover .name{color:var(--accent);}
  .family .fam.active{box-shadow:inset 0 2px 0 var(--accent);}
  .family .fam.active .name{color:var(--ink);}
  .family .fam.active .name .a{color:var(--accent);}
  .family .fam.active:hover .name{color:var(--accent);}
  /* An inset box-shadow reads as a ring but is dropped entirely in forced-colors
     mode, so the suite tabs used the one focus style on the page that could
     vanish. Same treatment as everything else now. */
  .family .fam:focus-visible{outline:2px solid var(--accent-deep);outline-offset:-2px;}
  /* panels stacked in one grid cell → constant height (no page jump) + cross-fade */
  .hero-text,.hero-demo{min-width:0;display:grid;align-items:start;}
  .hpanel,.dpanel{grid-area:1/1;opacity:0;visibility:hidden;transform:translateY(6px);
    transition:opacity .6s ease,transform .6s cubic-bezier(.22,.8,.2,1),visibility .6s;}
  .hpanel.active,.dpanel.active{opacity:1;visibility:visible;transform:none;}
  .hp-eyebrow{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);margin: 0 0 var(--s-3);}
  .hp-eyebrow .live{color:var(--good);}
  .hp-eyebrow .soon{color:var(--mark);}
  .demo .concept{margin-left:auto;font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--mark);border: var(--hairline) solid var(--rule-soft);padding: .16rem var(--s-2);}
  .demo-brief .brief-label{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent);margin: 0 0 var(--s-2);}
  .demo-brief .brief-bl{font-family:var(--font-display);font-variation-settings:"wght" 480;font-size: var(--t-4);line-height: calc(var(--s-1) * 6);color:var(--ink);margin: 0 0 var(--s-4);}
  .demo-brief .brief-row{font-size: var(--t-4);line-height: calc(var(--s-1) * 7);color:var(--ink-soft);margin: 0 0 var(--s-4);}
  .demo-brief .brief-row:last-of-type{margin-bottom:0;}
  .demo-teaser .teaser-draft{font-family:var(--font-display);font-variation-settings:"wght" 440;font-size: var(--t-4);line-height: calc(var(--s-1) * 6);color:var(--ink);margin: 0 0 var(--s-4);}
  .demo-teaser .row:first-of-type,.demo-brief .row:first-of-type{border-top:0;}

  /* ---- the suite (ruled list) ---- */
  .suite{padding-top:var(--section);}
  .suite .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,30rem),1fr));column-gap: var(--s-5);border-top: var(--hairline) solid var(--rule-soft);margin-top: var(--s-3);}
  /* Finding 19, the front door's copy of the same defect. The hover slide used to
     animate the left padding, which reflows every frame and re-wraps the blurb
     under the cursor; the text ran
     16px over 320ms while the arrow ran 8px over 280ms — two clocks in one
     gesture. One transform, one duration, one curve. */
  a.tool{display:grid;grid-template-columns:1fr auto;align-items:start;column-gap: var(--s-3);padding: var(--s-4) 0;border-bottom: var(--hairline) solid var(--rule-soft);transition:background 180ms ease;}
  a.tool > *{transition:transform 180ms cubic-bezier(.22,.8,.2,1);}
  a.tool:hover{background:var(--paper-deep);}
  a.tool:hover > *{transform:translateX(1rem);}
  .tool .tag{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent);margin: 0 0 var(--s-2);}
  .tool .tname{font-family:var(--font-display);font-variation-settings:"wght" 600;font-size: var(--t-6);line-height: calc(var(--s-1) * 7);letter-spacing: var(--track-tight);color:var(--ink);margin: 0 0 var(--s-2);}
  .tool .tname .acc{color:var(--accent);font-variation-settings:"wght" 400;}
  .tool .desc{font-size: var(--t-3);line-height: calc(var(--s-1) * 6);color:var(--ink-soft);margin:0;max-width:48ch;}
  .tool .arrow{align-self:center;font-family:var(--font-display);font-variation-settings:"wght" 400;font-size: var(--t-6);color:var(--rule);transition:color 180ms ease;}
  a.tool:hover .arrow{color:var(--accent);}

  /* ---- why us ---- */
  .why{padding-top:var(--section);}
  .why .points{display:flex;flex-direction:column;gap: var(--s-4);max-width:62ch;margin-top: var(--s-2);}
  .why .pt{display:flex;gap: var(--s-3);align-items:baseline;}
  .why .pt .g{flex:0 0 auto;color:var(--accent);font-family:var(--font-display);font-variation-settings:"wght" 400;font-size: var(--t-6);line-height: calc(var(--s-1) * 7);}
  .why .pt p{margin:0;font-size: var(--t-4);line-height: calc(var(--s-1) * 7);color:var(--ink-soft);}
  .why .pt strong{font-family:var(--font-display);font-variation-settings:"wght" 600;font-weight:normal;color:var(--ink);}

  /* ---- the bar + how it works (umbrella content) ---- */
  .section-h{font-family:var(--font-display);font-variation-settings:"wght" 620;font-size: var(--t-7);line-height: calc(var(--s-1) * 11);letter-spacing: var(--track-tight);color:var(--ink);margin: 0 0 var(--s-4);text-wrap:balance;}
  .thebar{padding-top:var(--section);}
  .thebar .section-h{margin-bottom: var(--s-2);}
  /* Hero + section-heading responsive ramp — uniform with the tool pages
     (assets/css/editorial-frame.css / suite.css) so every surface matches. */
  /* The 900px and 600px heading tiers are gone. Each carried its own floor and
     ceiling so they never met the base ramp, and the hero GREW as the page
     narrowed across 601 -> 600px (25.53 -> 29.92px, measured 2026-07-27).
     One continuous clamp per element cannot have a seam. Findings 15 and 17.

     The ramp now covers .plan .price, .thebar .bar-lead and .finalcta .big as
     well. It used to reach only h1.display and .section-h, so .plan .price sat
     at a fixed 1.8rem and the word "Custom" was the largest text on the page at
     390px — 29.41px against a 19.61px hero. */
  .thebar .bar-lead{font-family:var(--font-display);font-variation-settings:"wght" 460;font-size: var(--t-7);line-height: calc(var(--s-1) * 12);letter-spacing: var(--track-tight);color:var(--ink);margin: 0 0 var(--s-3);max-width:34ch;text-wrap:balance;}
  .thebar .bar-lead .acc{color:var(--accent);}
  .thebar .bar-body{font-size: var(--t-4);line-height: calc(var(--s-1) * 8);color:var(--ink-soft);max-width:56ch;margin:0;}
  .howitworks{padding-top:var(--section);}
  .steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,15rem),1fr));gap: var(--s-5);}
  .step{border-top:2px solid var(--accent-deep);padding-top: var(--s-3);}
  .step .step-n{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: normal;color:var(--accent);display:block;margin: 0 0 var(--s-2);}
  .step h3{font-family:var(--font-display);font-variation-settings:"wght" 560;font-size: var(--t-5);letter-spacing: var(--track-tight);color:var(--ink);margin: 0 0 var(--s-2);}
  .step p{font-size: var(--t-3);line-height: calc(var(--s-1) * 6);color:var(--ink-soft);margin:0;}

  /* ---- pricing ---- */
  .pricing{padding-top:var(--section);}
  /* Same rank as .section-h, so the same ramp and the same weight. This was
     left behind when .section-h moved onto the continuous ramp, leaving two
     sizes for one rank: 36.00px here against 37.44px there. */
  .pricing h2{font-family:var(--font-display);font-variation-settings:"wght" 620;font-size: var(--t-7);line-height: calc(var(--s-1) * 11);letter-spacing: var(--track-tight);color:var(--ink);margin: 0 0 var(--s-1);}
  .pricing .ph{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);margin: 0 0 var(--s-4);}
  .pricing .plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,13.5rem),1fr));border-top: var(--hairline) solid var(--rule-soft);border-left: var(--hairline) solid var(--rule-soft);}
  .plan{border-right: var(--hairline) solid var(--rule-soft);border-bottom: var(--hairline) solid var(--rule-soft);padding: var(--s-4) var(--s-4);display:flex;flex-direction:column;gap: var(--s-3);}
  .plan.hi{background:var(--paper-warm);}
  .plan .pn{font-family:var(--font-display);font-variation-settings:"wght" 560;font-size: var(--t-5);color:var(--ink);display:flex;align-items:baseline;justify-content:space-between;gap: var(--s-2);}
  .plan .pn .pop{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent);}
  .plan .price{font-family:var(--font-display);font-variation-settings:"wght" 460;font-size: var(--t-6);letter-spacing: var(--track-tight);color:var(--ink);}
  .plan .price small{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);display:block;margin-top:.2rem;}
  .plan .feats{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap: var(--s-2);flex:1;}
  .plan .feats li{font-size: var(--t-3);color:var(--ink-soft);display:flex;gap: var(--s-2);align-items:baseline;}
  .plan .feats li::before{content:"·";color:var(--accent);font-weight:700;}

  /* ---- final cta ---- */
  .finalcta{margin-top:var(--section);border-top:2px solid var(--accent-deep);background:var(--paper-warm);padding:clamp(2.2rem,4vw,3.4rem) clamp(1.6rem,3vw,2.6rem);display:flex;align-items:center;justify-content:space-between;gap: var(--s-4);flex-wrap:wrap;}
  .finalcta .ey{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent);margin: 0 0 var(--s-3);}
  .finalcta .big{font-family:var(--font-display);font-variation-settings:"wght" 480;font-size: var(--t-7);line-height: calc(var(--s-1) * 11);letter-spacing: var(--track-tight);color:var(--ink);max-width:34ch;margin:0;}

  /* ---- footer ---- */
  /* display:block is load-bearing, not tidying. suite.css:874 styles `.foot` as
     a wrapping flex ROW with align-items:baseline, written for the small
     two-part footer on editorial/corporate ("© copy" left, "powered by" right).
     The front door reuses the class name for something structurally different:
     a five-column link grid stacked above a colophon. Those two rulesets
     collided — the grid and the colophon became baseline-aligned flex siblings
     that wrapped, which is the "all awry" Ritu reported on 2026-07-28. Resetting
     to block lets .cols and .colophon below own their own layout. If suite.css's
     .foot is ever renamed, this reset can go with it. */
  footer.foot{display:block;margin-top:var(--section);border-top: var(--hairline) solid var(--rule-soft);padding-top: var(--s-5);padding-bottom: var(--s-6);}
  /* The five tracks had hard minimums (15rem + 4x8rem + 4x2rem gap = 55rem, about
     990px at an 18px root, plus page gutters) but only collapsed to two columns
     at 860px. Between roughly 861 and 1100px the grid was wider than its
     container and the right-hand link column ran off the page. body{overflow-x:
     hidden} in suite.css hid it, so it never showed as a scrollbar — measured
     2026-07-27 at 1024px: .cols spanned 36..1026 in a 1009px viewport.
     min(100%, Xrem) is the idiom that cannot overflow: the track floor collapses
     to the container width instead of forcing it wider. Same pattern .steps
     already uses in this sheet. */
  .foot .cols{display:grid;grid-template-columns:minmax(0,1.5fr) repeat(4,minmax(0,1fr));gap: var(--s-4);align-items:start;}
  .foot .brand .logo img{height:46px;width:auto;display:block;margin-bottom: var(--s-2);}
  .foot .foot-descriptor{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);font-weight:500;letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--ink-soft);margin: 0 0 var(--s-5);}
  .foot .news{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);margin: 0 0 var(--s-3);}
  /* The newsletter was a bare <input> beside an <a href="#">: no form, no label,
     no name, no type. Nothing announced it, nothing could submit it, and no
     password manager or autofill could see it. Now a real form; the label is
     hidden visually, not from assistive tech (design review, finding 11). */
  .visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}
  .foot .signup{display:flex;gap: var(--s-2);max-width:21rem;}
  .foot .signup button{cursor:pointer;font-family:inherit;}
  /* Curved with the rest (Ritu, 2026-08-07: ALL input boxes). I had left this
     one sharp on an estimate that it was ~35px tall, where a 16px corner would
     read as a capsule. Measured, it is 40px, so the corner leaves 8px of
     straight edge top and bottom and sits in proportion. The estimate was the
     error, not the ruling. */
    /* 16px, not 12. Mobile Safari zooms the whole page when a focused text
     control is under 16px and does not zoom back out. MEASURED 2026-09-20 at
     358x620: this is the newsletter field on the PUBLIC front door, which is
     the first control a stranger ever touches. The 2026-09-20 U9 sweep raised
     27 controls on the eight editorial desks and never reached this sheet.
     tests/input-zoom-floor.test.js now reads every stylesheet, not one. */
    .foot .signup input{flex:1;min-width:0;border:1px solid var(--accent-deep);background:var(--paper);border-radius:var(--box);padding: var(--s-2) var(--s-2);font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-3);color:var(--ink);outline:none;}
  .foot .signup input::placeholder{color:var(--quiet);}
  .foot .colhead{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);margin: 0 0 var(--s-3);}
  .foot .links{display:flex;flex-direction:column;gap: var(--s-2);}
  /* width:max-content keeps the hover colour tight to the label, but on its own
     it also sets the grid track's min-content floor, so the last footer column
     could not shrink and ran off the page between about 861 and 1100px.
     max-width:100% lets the label wrap instead of forcing the track wider. */
  .foot .links a{font-size: var(--t-3);color:var(--ink-soft);transition:color .18s ease;width:max-content;max-width:100%;}
  .foot .links a:hover{color:var(--accent);}
  .foot .colophon{margin-top: var(--s-5);padding-top: var(--s-4);border-top: var(--hairline) solid var(--rule-soft);display:flex;align-items:center;justify-content:space-between;gap: var(--s-3);flex-wrap:wrap;}
  .foot .colophon .colo-left{display:flex;flex-direction:column;gap: var(--s-1);}
  .foot .colophon .descriptor-foot{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);font-weight:500;letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--ink-soft);}
  .foot .colophon .c{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: normal;color:var(--quiet);}
  .foot .colophon .pw{font-style:italic;font-size: var(--t-2);color:var(--quiet);}

  @media (max-width:860px){
    .hero{grid-template-columns:1fr;}
    /* four-suite rail → clean 2×2 grid (keeps tabs compact; hero stays near top) */
    .family{grid-template-columns:repeat(2,1fr);}
    .family .fam{border-right: var(--hairline) solid var(--rule-soft);border-bottom: var(--hairline) solid var(--rule-soft);}
    .family .fam:nth-child(2n){border-right:0;}      /* right column: no outer divider */
    .family .fam:nth-child(n+3){border-bottom:0;}    /* bottom row: no inner divider */
    .family .fam:nth-child(2n+1){padding-left:0;}    /* left column flush to edge */
    .foot .cols{grid-template-columns:1fr 1fr;}
    /* Keep the authored <br> break on mobile: the source uses it AS the space
       (e.g. "readership,<br>and…"), so hiding it glued words together. The
       smaller mobile hero size below lets each half sit on its own line. */
    /* Mobile: each stacked hero panel hugs the ACTIVE one instead of every
       panel reserving the tallest panel's height — that reserve left dead
       space ("the gap") under the shorter panels. Inactive panels go out of
       flow; the active one drives the height. Auto-advance is paused on mobile
       (hero JS) so this height only changes on a user tap → no page jump. */
    .hero-text,.hero-demo{position:relative;}
    .hpanel,.dpanel{position:absolute;top:0;left:0;right:0;}
    .hpanel.active,.dpanel.active{position:relative;}
  }
  /* Below ~340px a quarter-column is ~80px and "Editorial LIVE" cannot hold one
     line, so the status wraps and brings the uneven-cell hole straight back
     (measured at 320px: 22px of spread, two cells tall, two short). The whole
     point of the inline status is that no cell can leave a hole, so at the one
     width where it cannot keep that promise it stands down. Each suite's status
     is still stated on its own panel below. */
  @media (max-width:340px){
    .fam .state{display:none;}
  }

  @media (max-width:560px){
    nav.top{gap: var(--s-3);}
    /* Pills: fill the capsule so they don't read as outsized — a touch more
       label, a touch less horizontal padding. Measured 2026-07-27 at 390px: 43.8px,
     which is why min-height:var(--touch-min) is now set explicitly below rather
     than left to padding to approximate. The old comment claimed "a tappable
     ~44px" and had never been re-measured. */
    .cta{font-size: var(--t-2);padding: var(--s-3) var(--s-3);min-height:var(--touch-min);}
    .cta.lg{font-size: var(--t-2);padding: var(--s-2) var(--s-3);}
    .masthead .descriptor{display:none;}

    /* ---- phone masthead: brand + one action, on one line ----
       Measured 2026-07-28 at 390px: 226px tall, a quarter of the screen before
       a word of content. .masthead wraps, so nav.top dropped below the wordmark,
       and inside it the demo pill dropped again onto a third row. Ritu:
       "bloated", "REQUEST A DEMO taking up acres of space", "clearly too big,
       overshadowing the wordmark".

       The four navlinks are same-page anchors (#hero, #pricing, #why) plus a
       Log in that currently points at "#". On a page you scroll through in that
       order they cost a row and buy nothing, so they come out on a phone and the
       masthead holds what a phone masthead should: the mark, and the one thing
       we want tapped. Nothing is unreachable — the sections are below. */
    .masthead{flex-wrap:nowrap;gap: var(--s-3);padding:1rem var(--gutter) .9rem;}
    nav.top a.navlink{display:none;}
    /* NOT gap:0 any more. That zero dates from when this bar held one control
       once the nav words were hidden. It now holds two, and Ritu saw the result
       on his phone: the account capsule "almost touching request a demo".
       MEASURED at 560 before this: the capsule ended at 405 and the button
       began at 405. Two controls with nothing between them. */
    nav.top{gap: var(--s-2);flex:none;}
    /* Painted shorter than the 36px wordmark so the brand keeps the weight. The
       tap target stays at the full 44px floor via ::after, the same paint/target
       split used on .mast-nav-link in suite.css. */
    .masthead .cta{position:relative;min-height:0;height:32px;font-size: var(--t-1);
      letter-spacing: normal;padding: 0 var(--s-2);white-space:nowrap;}
    .masthead .cta::after{content:"";position:absolute;left:0;right:0;top:50%;
      transform:translateY(-50%);height:var(--touch-min);}

    /* ---- phone footer ----
       Four link lists stacked one per row measured 865px on their own. Two
       columns halves that at no cost to legibility: the lists are 4-5 short
       items each, and the tallest pair sets a tidy edge. The signup keeps the
       full width because an email field at 172px is not a field, it is a slot.
       align-items:start stops a short column stretching to its neighbour. */
    .foot .cols{grid-template-columns:1fr 1fr;gap: var(--s-4) var(--s-3);align-items:start;}
    .foot .news-col{grid-column:1 / -1;}
    .foot .signup{max-width:none;}
    .foot .colophon{margin-top: var(--s-5);gap: var(--s-2);}

    /* ---- phone pricing ----
       Five plan cards stacked measured 1,737px: two full phone screens for a
       block whose prices still read "[Pricing to confirm]". The card shape stops
       earning its keep at this width — five identical bordered boxes, each with
       its name, price, features and action on four separate rows, is a lot of
       scrolling to learn there are five tiers.

       On a phone it becomes a price LIST instead: name and price share a line,
       features sit under them, the action closes the row. Every tier and every
       word is kept; the vertical borders go because a one-column grid has no
       columns to divide. Roughly 1,737px down to ~1,050px. */
    /* Suite rail: each cell measured 90px to carry one word and a four-letter
       tag, so the rail cost 181px before the hero began. The padding and the
       inner gap are desktop values; tightening them takes it to ~150px.

       The tag was moved up BESIDE the name first, which is the bigger saving,
       and reverted: overflow_check caught "Corporate" plus its tag needing
       176px inside a 140px track at 320px, and the same at 360px, which is the
       most common Android width. A two-column rail cannot hold a name and a
       chip on one line at those widths. Stacked and tightened is the safe
       trade. Do not re-try the row layout without re-running the gate. */
    .family .fam{padding: var(--s-3) var(--s-2);gap: var(--s-1);}

    .pricing .plans{border-left:0;}
    .plan{display:grid;grid-template-columns:1fr auto;align-items:baseline;
      column-gap: var(--s-3);row-gap: var(--s-2);padding: var(--s-3) 0;border-right:0;}
    .plan.hi{padding-left: var(--s-3);padding-right: var(--s-3);}
    .plan .pn{grid-column:1;font-size: var(--t-4);}
    .plan .price{grid-column:2;text-align:right;font-size: var(--t-4);white-space:nowrap;}
    .plan .price small{display:block;font-size: var(--t-1);margin-top:.1rem;}
    .plan .feats{grid-column:1 / -1;gap: var(--s-1);}
    .plan .feats li{font-size: var(--t-3);}
    .plan .typeset,.plan .cta{grid-column:1 / -1;justify-self:start;}
  }
  @media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;}}
  /* ===== WHY US — large arrow-led credo, spread horizontally ===== */
  .why .pillars{display:grid;grid-template-columns:repeat(3,1fr);border-top:2px solid var(--accent);margin-top: var(--s-3);}
  .why .pillar{padding: var(--s-4) var(--s-4) var(--s-5);border-right:1px solid var(--rule-soft);display:flex;flex-direction:column;gap: var(--s-2);}
  .why .pillar:first-child{padding-left:0;}
  .why .pillar:last-child{border-right:0;padding-right:0;}
  .why .pillar .g{font-family:var(--font-display);font-variation-settings:"wght" 400;font-size:3rem;line-height:.66;color:var(--accent);}
  .why .pillar h3{font-family:var(--font-display);font-variation-settings:"wght" 600;font-size: var(--t-5);letter-spacing: var(--track-tight);line-height: calc(var(--s-1) * 6);color:var(--ink);margin:0;}
  .why .pillar p{font-size: var(--t-4);line-height: calc(var(--s-1) * 7);color:var(--ink-soft);margin:0;max-width:32ch;}
  @media (max-width:760px){
    .why .pillars{grid-template-columns:1fr;border-top:0;margin-top: var(--s-2);}
    .why .pillar{border-right:0;border-top:2px solid var(--accent);padding: var(--s-4) 0;}
    .why .pillar .g{font-size:2.4rem;}
  }

  /* ===== THE BAR — full-measure text + rotating before/after proof ===== */
  /* The text column took up to 34rem before the proof panel got anything, so at
     900px the panel was left about 170px and .tag-mark (white-space:nowrap) and
     the dot row pushed past the viewport edge. Giving the panel a real floor and
     letting the text column yield keeps both inside at every width. */
  .thebar .bar-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(min(100%,22rem),1fr);gap:clamp(2rem,4vw,3.5rem);align-items:start;}
  .thebar .bar-grid > *{min-width:0;}
  .bar-text .bar-lead{max-width:34ch;}
  .bar-text .bar-body{max-width:54ch;}
  .proof{border: var(--hairline) solid var(--rule-soft);background:var(--paper-warm);min-width:0;}
  .proof .pbar{display:flex;align-items:center;justify-content:space-between;gap: var(--s-3);padding: var(--s-3) var(--s-3);border-bottom: var(--hairline) solid var(--rule-soft);background:var(--paper-deep);}
  .proof .pbar .t{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);}
  .proof .pbar .tag-mark{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--mark);border: var(--hairline) solid var(--mark);padding: .16rem var(--s-2);white-space:nowrap;}
  .proof .pbody{padding: var(--s-4) var(--s-4) var(--s-4);}
  .estack{display:grid;}
  .epanel{grid-area:1/1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,10.5rem);gap: var(--s-4);align-items:center;opacity:0;visibility:hidden;transition:opacity .55s ease,visibility .55s;}
  .epanel.active{opacity:1;visibility:visible;}
  .gstack{display:flex;flex-direction:column;gap: var(--s-2);min-width:0;}
  .ga-cap{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--quiet);margin: 0 0 var(--s-2);}
  .ga-cap.good{color:var(--good);}
  .ga-arrow{font-family:var(--font-display);font-size: var(--t-4);color:var(--mark);margin:.05rem 0 .15rem;line-height: calc(var(--s-1) * 5);}
  .galley{font-family:var(--font-body);font-size: var(--t-4);line-height: calc(var(--s-1) * 8);font-weight:450;color:var(--ink-soft);margin:0;}
  .after .galley{color:var(--ink);font-weight:500;}
  .ann{text-decoration-thickness:2px;text-underline-offset:3px;text-decoration-color:transparent;}
  .ann.strike{text-decoration-line:line-through;}
  .ann.under{text-decoration-line:underline;}
  .epanel.active .ann{animation:drawMark .55s ease both;}
  .margins{display:flex;flex-direction:column;gap: var(--s-3);border-left: var(--hairline) solid var(--rule-soft);padding-left: var(--s-3);}
  .margins .mnote{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);font-weight:500;letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--mark);line-height: calc(var(--s-1) * 5);opacity:0;}
  .epanel.active .mnote{animation:fadeNote .5s ease both;}
  .proof .pfoot{display:flex;align-items:center;justify-content:space-between;padding: var(--s-2) var(--s-3);border-top: var(--hairline) solid var(--rule-soft);}
  /* The .6rem padding was sized for a text row. Once the 44px pause control sets
     the height it is only wasted space: the row measured 66.6px against the
     ~56px Ritu approved. Trimmed ONLY while the control is actually showing, so
     that under reduced motion and without JS the row keeps its original 43.4px
     rather than ending up tighter than it started. Measured after: 57.6px with
     the control at 1440/900, 56.4px at 390; 43.4px unchanged without it. */
  .proof .pfoot:has(.rot-hold:not([hidden])){padding: var(--s-2) var(--s-3);}
  .proof .pfoot .slug{font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);letter-spacing: var(--track-caps);text-transform:uppercase;color:var(--accent-deep);}
  .proof .edots{display:flex;gap: var(--s-1);}
  .proof .edots i{width:.42rem;height:.42rem;background:var(--rule);transition:background .3s ease;}
  .proof .edots i.on{background:var(--mark);}
  /* Hold the rotation (WCAG 2.2.2). The stack auto-advances forever and the
     focusin/focusout pair here was dead: the panels are built from divs and
     paragraphs, so the region has ZERO focusable children and the comment at
     those listeners claimed a keyboard fix that could never fire. It sits beside
     the dots because the dots already say "this rotates". Outline pill, never
     filled, at the 44px floor -- which grows this row from 34px to 56px, Ritu's
     call 2026-08-03. --rule is #868A8A on this ground (3.16:1), a real boundary,
     unlike the Social sheet's --rule. */
  .proof .pfoot-right{display:flex;align-items:center;gap: var(--s-2);}
  .proof .rot-hold{display:inline-flex;align-items:center;min-height:var(--touch-min);
    background:transparent;border:1px solid var(--rule);border-radius:var(--pill);
    color:var(--quiet);font-family: var(--font-display); font-size-adjust: var(--x-adjust);font-size: var(--t-1);
    letter-spacing: var(--track-caps);text-transform:uppercase;padding: var(--s-2) var(--s-3);cursor:pointer;}
  .proof .rot-hold:hover{border-color:var(--accent);color:var(--accent);}
  .proof .rot-hold[hidden]{display:none;}
  @keyframes drawMark{from{text-decoration-color:transparent;}to{text-decoration-color:var(--mark);}}
  @keyframes fadeNote{from{opacity:0;transform:translateX(-6px);}to{opacity:1;transform:none;}}
  @media (max-width:860px){
    .thebar .bar-grid{grid-template-columns:1fr;}
    .epanel{grid-template-columns:1fr;}
    .margins{flex-direction:row;flex-wrap:wrap;gap: var(--s-2) var(--s-4);border-left:0;border-top: var(--hairline) solid var(--rule-soft);padding-left:0;padding-top: var(--s-3);}
  }
  @media (prefers-reduced-motion:reduce){
    .epanel{transition:none;}
    .epanel.active .ann{text-decoration-color:var(--mark);animation:none;}
    .epanel.active .mnote{opacity:1;transform:none;animation:none;}
  }
  

  /* Minimal de-tell (2026-07-14): display font → Schibsted Grotesk, paper → teal-biased grey.
     Teal, navy, ink, chrome and layout are unchanged. Body serif (Newsreader) unchanged. */
  
  h1.display{ font-variation-settings:"wght" 780; letter-spacing: var(--track-hero); }
  h1.display .you, h1.display .tw{ font-variation-settings:"wght" 780; }

  /* ===================================================================== */
  /* THE BANDS — the front-door brightening, 2026-08-05.                   */
  /*                                                                        */
  /* The diagnosis this closes: the page was one grey, every surface within */
  /* about 6% of every other. Ritu, naming what he liked on sudowrite.com:  */
  /* "as you scroll down, there are different elements and surprises which  */
  /* pop up, keeping the visitor engaged", and "the sketches in the         */
  /* background."                                                           */
  /*                                                                        */
  /* What he ruled, and what is therefore NOT here: no press vocabulary     */
  /* (halftone screens, registration marks) - "the whole grammar is not     */
  /* print nor newspapers. It's a modern product for all kinds of content,  */
  /* smart writing workflows", and DESIGN-SYSTEM.md governs Editorial only. */
  /* No photographs - "in what context would I just insert some pictures    */
  /* onto the front door?" No soft gradient field. No colour token changed. */
  /*                                                                        */
  /* THE ONE STRUCTURAL MOVE: .wrap stops being the width limiter and each  */
  /* SECTION carries the frame padding instead, so a section can paint edge */
  /* to edge while its contents still land on the product frame. That is    */
  /* the house idiom, already live on .masthead above, suite.css:186 and    */
  /* social-dark.css:157. NEVER 100vw: suite.css sets scrollbar-gutter:     */
  /* stable, so 100vw over-measures by about 15px and overflow_check.mjs    */
  /* would see it.                                                          */
  /* ===================================================================== */
  .wrap{width:100%;max-width:none;margin:0;}
  .wrap > nav,
  .wrap > main > section,
  .wrap > footer,
  .band{padding-inline:calc((100% - var(--frame)) / 2);}

  /* Ritu, on the mockup: "Too large a gap between WHY US and the next
     section." Measured at 1440: every section carried padding-top 99.75px and
     NO section has any bottom padding, so the whole page ran on one 100px gap
     and the short "Why us" pillars floated in it. Last pillar to "The bar"
     eyebrow was 132px of ink gap; it is now 104px. Tightened globally rather
     than at that one seam, because a single narrowed gap is the sort of
     one-off this page keeps being caught for. 2026-08-05, measured at 1440. */
  :root{--section:clamp(2.75rem, 5vw, 4.5rem);}

  .band{
    background:var(--accent-deep);color:#E7EEF4;
    padding-block:clamp(3.4rem, 6vw, 5.4rem);
    margin-top:var(--section);
    --ico-color:currentColor;
  }
  .band-h{
    font-family:var(--font-display);font-variation-settings:"wght" 600;
    letter-spacing: var(--track-tight);font-size: var(--t-7);
    line-height: calc(var(--s-1) * 12);margin: 0 0 var(--s-5);max-width:26ch;color:#FBFAF6;
  }

  /* "The bar" loses its sidebar and becomes one measured column. */
  .thebar .bar-grid{display:block;}
  .thebar .bar-text{max-width:62ch;}

  /* The proof at band scale. Built for a 22rem sidebar, it stacked BEFORE
     above AFTER with a down arrow; at this width that left half the band empty
     and buried the comparison. Side by side is the whole point of taking it
     out of the sidebar: the eye compares two columns, not two paragraphs
     separated by an arrow.

     The TOKENS are rescoped rather than each rule overridden. The proof is a
     light-theme component whose own rules are specific (.proof .pbar .tag-mark
     is 0,3,0) and some of its colour is painted from @keyframes drawMark, which
     reads var(--mark) - so the day amber #76510F was landing at 2.04:1 on this
     navy, the same failure class as the invisible button marks fixed earlier
     today. The night amber reads 5.3:1 on the panel. Scoped to .proof and NOT
     to .band-proof: the band paints its own background from var(--accent-deep),
     so rescoping that token on the band itself turns the navy pale blue.
     Measured 2026-08-05 at 1440x900. */
  .band-proof .proof{
    --mark:#CBA15A;--good:#56B6BF;--quiet:#8FB3CE;
    --rule:#1E4F80;--rule-soft:#1E4F80;
    --ink:#EAF3F5;--ink-soft:#DCE8F1;
    --paper-warm:#0C3555;--paper-deep:#0A2E4A;--accent-deep:#8FB3CE;
    background:#0C3555;border: var(--hairline) solid #1E4F80;
  }
  .band-proof .pbar{background:#0A2E4A;border-bottom-color:#1E4F80;}
  .band-proof .pbody{padding:clamp(1.5rem, 2.8vw, 2.4rem);}
  .band-proof .pfoot{background:#0A2E4A;border-top-color:#1E4F80;}
  @media (min-width:56rem){
    .band-proof .epanel{grid-template-columns:minmax(0, 1fr);}
    .band-proof .gstack{display:grid;grid-template-columns:1fr auto 1fr;
      gap:clamp(1.4rem, 2.6vw, 2.6rem);align-items:start;}
    .band-proof .ga-arrow{margin:0;align-self:center;transform:rotate(-90deg);color:#56B6BF;}
  }
  .band-proof .galley{color:#DCE8F1;line-height:1.62;}
  .band-proof .ga.before .galley{color:#9FB6CA;}
  /* The notes become a row under the comparison. The base rule is
     flex-direction:column with a left rule and left padding, so all three have
     to be reset or the notes stack and stretch the full width of the band. */
  .band-proof .margins{
    display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;gap: var(--s-2);
    border-left:0;padding-left:0;border-top: var(--hairline) solid #1E4F80;
    margin-top:clamp(1.3rem, 2.3vw, 1.9rem);padding-top:clamp(1rem, 1.9vw, 1.4rem);
  }
  .band-proof .margins .mnote{
    flex:0 0 auto;margin:0;color:#A9C4D8;border: var(--hairline) solid #2A628F;
    border-radius:var(--pill);padding:.42em .9em;background:#0A2E4A;line-height:1.2;
  }
  .band-proof .rot-hold{color:#DCE8F1;border-color:#2A628F;}
  @media (hover: hover){.band-proof .rot-hold:hover{border-color:#56B6BF;color:#56B6BF;}}
  .band-proof .edots i{background:#2A628F;}
  .band-proof .edots i.on{background:#56B6BF;}

  /* The final CTA was already a painted band, just clipped to the content
     column. Freeing it costs two lines. --ico-color is declared because the
     selector contains "cta" and paints var(--accent-deep), which is exactly
     what tests/test_css_architecture.py::MarkColourTest checks for. */
  .finalcta{
    background:var(--accent-deep);color:#FBFAF6;border-top:0;
    margin-top:var(--section);padding-block:clamp(3rem, 5.5vw, 4.6rem);
    padding-inline:calc((100% - var(--frame)) / 2);
    --ico-color:currentColor;
  }
  .finalcta .ey{color:#8FB3CE;}
  .finalcta .big{color:#FBFAF6;}
  .finalcta .cta.inverse{background:transparent;color:#FBFAF6;border-color:#FBFAF6;--ico-color:currentColor;}
  @media (hover: hover){.finalcta .cta.inverse:hover{background:#FBFAF6;color:var(--accent-deep);}}

  /* The four suites stop being four grey words. Choosing a suite is what the
     front door is FOR, so the row reads as four destinations. */
  .suiterail .family{gap:1px;background:var(--rule-soft);border: var(--hairline) solid var(--rule-soft);}
  .suiterail .fam{background:var(--paper);padding: var(--s-4) var(--s-3) var(--s-3);
    position:relative;transition:background 140ms ease;}
  /* Ritu: "In the SUITES panel, E of EDITORIAL rimming the box." The rule above
     at .family .fam:first-child{padding-left:0} belonged to the RAIL design,
     which deliberately ran the first suite flush to the content edge with no box
     around it. Now that each suite is a box, that flush edge puts the E hard
     against the rim while the other three sit 21px in. 2026-08-05.

     WIDENED 2026-09-08, from :first-child to every cell, because the rail
     design left a second flush rule behind and it was still firing. At 860 and
     below the grid becomes 2x2 and `.family .fam:nth-child(2n+1)` runs the
     LEFT COLUMN flush, which is cells one and three: Editorial and Social. The
     2026-08-05 fix named the first child only, so Editorial was rescued and
     Social was not, and at 390 its S sat hard on the rim with padding-left 0
     while the other three sat 16px in. Measured, before: 16, 16, 0, 16. The
     flush edge belongs to a design where these were four grey words with no
     box around them; not one of the four wants it now. */
  .suiterail .family .fam{padding-left: var(--s-3);}
  .suiterail .fam::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;
    background:var(--sc, transparent);}
  .suiterail .fam:nth-child(1){--sc:#156169;}
  .suiterail .fam:nth-child(2){--sc:#2F5C9E;}
  .suiterail .fam:nth-child(3){--sc:#B4436C;}
  .suiterail .fam:nth-child(4){--sc:#8A6A1F;}
  .suiterail .fam .name{font-variation-settings:"wght" 600;letter-spacing: var(--track-tight);}
  .suiterail .fam .state{color:var(--sc);}
  .suiterail .fam.soon .state{color:var(--quiet);}
  .suiterail .fam.active{background:var(--paper-warm);}
  @media (hover: hover){.suiterail .fam:hover{background:var(--paper-warm);}}

  /* The reveal. One quiet entrance per section, on the strong ease-out curve
     from the emil framework; transform and opacity only, transitions not
     keyframes. Under reduced motion the fade stays and the movement goes. */
  .js [data-step]{opacity:0;transform:translateY(18px);
    transition:opacity 640ms cubic-bezier(0.23, 1, 0.32, 1),
               transform 640ms cubic-bezier(0.23, 1, 0.32, 1);}
  .js [data-step].on{opacity:1;transform:none;}
  @media (prefers-reduced-motion: reduce){
    .js [data-step]{opacity:1;transform:none;transition:none;}
  }


/* Per-band text sizes, appended by preview/build-precision.mjs
   --apply-type. The product's root font is a clamp, so one rem is a
   different number of pixels at each width and a single mapped value
   would be wrong everywhere except the width it was mapped at. These
   carry identical specificity to the rule above and come later, which is
   how the narrower band wins. */
@media (max-width: 620px) {
.hero .lede {
  font-size: var(--t-4);
  /* The leading follows the type. Nine steps of the baseline grid was drawn for
     23px; against this 19px it reads 1.89, and a page of body copy set at 1.89
     is what he saw as a gap between sentences. Seven steps is 28px, 1.47.
     Ritu, 2026-09-13: "symmetry is the essence of this project." */
  line-height: calc(var(--s-1) * 7);
}
}
@media (max-width: 620px) {
.demo .ctrl {
  font-size: var(--t-2);
}
}
@media (max-width: 620px) {
.demo .row {
  font-size: var(--t-3);
}
}
@media (max-width: 620px) {
.demo .diaghead .s {
  font-size: var(--t-3);
}
}
@media (max-width: 620px) {
.demo-brief .brief-row {
  font-size: var(--t-3);
}
}
@media (max-width: 620px) {
.section-h {
  font-size: var(--t-5);
}
}
@media (max-width: 620px) {
.thebar .bar-lead {
  font-size: var(--t-5);
  /* A display leading drawn for 40px type, left behind when the type stepped
     down. Ritu, 2026-09-13: "symmetry is the essence of this project." */
  line-height: calc(var(--s-1) * 8);
}
}
@media (max-width: 620px) {
.pricing h2 {
  font-size: var(--t-5);
}
}
@media (max-width: 620px) {
.plan .pn {
  font-size: var(--t-4);
}
}
@media (max-width: 620px) {
.plan .price {
  font-size: var(--t-4);
}
}
@media (max-width: 620px) {
.finalcta .big {
  font-size: var(--t-5);
  /* A display leading drawn for 40px type, left behind when the type stepped
     down. Ritu, 2026-09-13: "symmetry is the essence of this project." */
  line-height: calc(var(--s-1) * 8);
}
}
@media (max-width:560px) {
@media (max-width: 620px) {
.plan .feats li {
  font-size: var(--t-2);
}
}
}
@media (max-width: 620px) {
.band-h {
  font-size: var(--t-6);
}
}
@media (max-width: 430px) {
.cta.lg {
  font-size: var(--t-1);
}
}
@media (max-width: 430px) {
.typeset {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.demo .row .m {
  font-size: var(--t-1);
}
}
@media (max-width: 430px) {
.demo .note {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.demo-brief .brief-bl {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.tool .tname {
  font-size: var(--t-5);
}
}
@media (max-width: 430px) {
.tool .arrow {
  font-size: var(--t-5);
}
}
@media (max-width: 430px) {
.why .pt .g {
  font-size: var(--t-5);
}
}
@media (max-width: 430px) {
.section-h {
  font-size: var(--t-4);
}
}
@media (max-width: 430px) {
.thebar .bar-lead {
  font-size: var(--t-4);
  /* and again at the narrower band, for the same reason. */
  line-height: calc(var(--s-1) * 7);
}
}
@media (max-width: 430px) {
.pricing h2 {
  font-size: var(--t-4);
}
}
@media (max-width: 430px) {
.plan .price {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.plan .feats li {
  font-size: var(--t-2);
}
}
@media (max-width: 430px) {
.foot .colophon .pw {
  font-size: var(--t-1);
}
}
@media (max-width:560px) {
@media (max-width: 430px) {
.cta {
  font-size: var(--t-1);
}
}
}
@media (max-width:560px) {
@media (max-width: 430px) {
.plan .pn {
  font-size: var(--t-3);
}
}
}
@media (max-width:560px) {
@media (max-width: 430px) {
.plan .price {
  font-size: var(--t-3);
}
}
}
@media (max-width: 430px) {
.why .pillar p {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.ga-arrow {
  font-size: var(--t-3);
}
}
@media (max-width: 430px) {
.band-h {
  font-size: var(--t-5);
}
}

/* Ritu, 2026-09-12: "the wordmark on the landing page and tools are too tiny",
   and "Do apps have such tiny identities?" The tools went to 30px in a 54px
   bar and the other two landing pages to 46px; this one was still drawing 36px
   in a 76px bar, which made it the smallest mark on the widest chrome.

   It is written HERE, and a first attempt in suite.css did nothing: index.html
   loads suite.css and THEN this sheet, so an equal-specificity rule over there
   can never win. That is the third time in one day a rule was written into a
   sheet that could not reach the page. Measured at 360 from 36 to 50px:
   nothing overflows and the bar does not grow.

   40px, not 46: the app's tool bars cannot carry 46 without truncating the
   story name beside the mark, so the whole product uses the one number and the
   landing page cannot drift above the tools it fronts. See the measurement
   table in editorial-frame.css. */
@media (max-width: 699.98px) {
  .masthead .logo img { height: 40px; }
}
