/* ==========================================================================
   EQUILIBRIUM — art direction
   ==========================================================================
   Accounting is the discipline of bringing things into balance. The books
   balance, the stones balance, the variance resolves to zero.

   The palette is sampled from the hero photograph rather than invented, so
   the two can never disagree:
     paper      #F6F5F1  warm off-white ground
     graphite   #1D1B23  the stones, a black with a violet cast
     ultramarine#110ED8  the stone resting on top

   Warm ground, cool ink — the combination the photograph already uses.
   Type: Newsreader (editorial voice) / Instrument Sans (product voice) /
         IBM Plex Mono (every figure, because in accounting the numbers
         are the product).
   Loaded after styles.css; overrides the inherited component layer.
   ========================================================================== */

:root{
  /* --- ground (warm, from the photograph's paper) -------------------- */
  --canvas:#F6F5F1;
  --paper:#FDFCF9;
  --paper-soft:#EDEBE5;

  /* --- ink (cool graphite, from the stones) -------------------------- */
  --ink:#17161C;
  --muted:#54535F;
  --quiet:#5E5D68;      /* 5.2:1 on --paper-soft, the darkest light ground */
  --line:rgba(23,22,28,.075);
  --line-soft:rgba(23,22,28,.055);
  --line-strong:rgba(23,22,28,.13);

  /* --- ultramarine: the stone on top --------------------------------
     Deeper and bluer than a default SaaS violet because it is taken from
     the photograph, not chosen next to it. */
  --indigo:#1D1BC4;
  --indigo-deep:#14119A;
  --indigo-soft:#EAE9FC;

  /* --- signals -------------------------------------------------------
     Green means balanced. Amber means it still needs a person. Nothing
     else on the page may use either. */
  --green:#237A57;
  --green-soft:#E4F0EA;
  --amber:#8A5A1E;
  --amber-soft:#F6EEE0;
  --lilac:#F3F2FD;
  --sage:#E4F0EA;

  --shadow:0 24px 72px rgba(24,22,46,.07);
  --ease:cubic-bezier(.22,1,.36,1);
  --settle:cubic-bezier(.16,1.06,.32,1);   /* overshoot, then rest */
  --content:1360px;
  --gutter:80px;

  /* v135 set every heading in one sans and that is the voice being restored.
     Instrument Sans rather than system-ui: same neutral grotesque character,
     but it renders identically on every OS instead of becoming SF Pro on a
     Mac, Segoe on Windows and Roboto on Android. */
  --font-display:var(--font-sans);
  --font-sans:"Instrument Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}

/* ==========================================================================
   Type
   ========================================================================== */

body{
  font-family:var(--font-sans);
  letter-spacing:-.005em;
}

/* The editorial voice. Optical sizing does real work at these ranges. */
.hero h1,
.section-heading h2,.features-heading h2,.integrations h2,.ai-copy h2,
.faq-intro h2,.closing-inner h2,.v113-outcomes h2,.v122-stack-heading h2,
.audience-row h3{
  font-family:var(--font-display);
  font-optical-sizing:auto;
  font-weight:510;
  font-variant-ligatures:common-ligatures;
  text-wrap:balance;
}

/* The accent word is indigo again. It had been switched to a display italic
   on the argument that emphasis should be a change of voice rather than of
   colour — which is a fine principle and the wrong call for this page. The
   indigo word is the one place the brand colour appears at size, it is what
   made the headings feel like this product rather than a template, and with
   the serif gone there is no second voice to change into. */
.hero h1 em,.section-heading h2 em,.features-heading h2 em,.integrations h2 em,
.ai-copy h2 em,.v113-outcomes h2 em,.faq-intro h2 em,.closing-inner h2 em{
  font-family:inherit;
  font-style:normal;
  font-weight:inherit;
  color:var(--indigo);
}

/* Fluid scale — replaces the fixed px steps in the inherited media queries. */
.hero h1{
  max-width:14ch;
  font-size:clamp(46px,6.6vw,92px);
  font-weight:510;
  line-height:.94;
  letter-spacing:-.032em;
}
.section-heading h2,.features-heading h2,.integrations h2,.ai-copy h2,
.v113-outcomes h2,.v122-stack-heading h2{
  max-width:19ch;
  /* Measured against v135: its h2 was 38px where this had grown to 60px, a
     57% jump. Section padding is near-identical between the two, so the lost
     air was never spacing — it was heading scale. Back to v135's own clamp,
     with a smaller floor so narrow screens are not shouted at. Tracking
     tightens to match: a grotesque at display size needs more negative
     tracking than the serif this replaces. */
  font-size:clamp(33px,3.25vw,50px);
  font-weight:510;
  line-height:1.02;
  letter-spacing:-.042em;
}
.closing-inner h2{
  font-size:clamp(36px,3.6vw,54px);
  font-weight:510;
  line-height:.99;
  letter-spacing:-.045em;
}
.faq-intro h2{
  font-size:clamp(28px,2.7vw,40px);
  font-weight:510;
  line-height:1.06;
  letter-spacing:-.038em;
}

/* The product voice stays a grotesque: card titles are UI, not editorial. */
.library-copy h3,.v112-card-copy h2,.audience-row h4{
  font-family:var(--font-sans);
  letter-spacing:-.018em;
}

/* Eyebrows: small, spaced, quiet. */
.section-heading>span,.features-heading>span,.eyebrow,.kicker{
  font-family:var(--font-sans);
  letter-spacing:.1em;
}

/* --------------------------------------------------------------------------
   Figures. Every number on the page is set in mono with tabular figures so
   columns line up and digits don't reflow while they animate.
   -------------------------------------------------------------------------- */
.ledger-number,
[data-agent-confidence],[data-ledger-variance],[data-bank-prepared],
[data-recon-variance],[data-recon-rate],[data-close-rate],[data-runway],
[data-arr],[data-attention],[data-progress],[data-ending-balance],
.close-meter b,.ledger-balance,.bank-amount,.match-amount,
.v112-focus-amount,.report-row b,.forecast-value{
  font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1,"zero" 1;
  letter-spacing:-.03em;
}

/* Any table-ish figure column, wherever it appears. */
.ledger-line,.bank-row,.match-row,.report-row,.v129-brand-row{
  font-variant-numeric:tabular-nums;
}

/* ==========================================================================
   Surface
   ========================================================================== */

/* Softer, more considered radii than the uniform 11px. */
.button{border-radius:8px;font-family:var(--font-sans);font-weight:600;letter-spacing:-.006em}
.button-primary{background:var(--indigo);color:#FDFCF9}
.button-primary:hover{background:var(--indigo-deep)}

/* Keyboard focus must be visible against paper. */
a:focus-visible,button:focus-visible,summary:focus-visible{
  outline:2px solid var(--indigo);
  outline-offset:3px;
  border-radius:4px;
}

/* ==========================================================================
   Motion — everything settles rather than simply appearing
   ========================================================================== */

html[data-motion="ready"] [data-reveal]{
  transform:translateY(14px);
  transition:opacity .7s var(--ease),transform .9s var(--settle);
}

@media (prefers-reduced-motion:reduce){
  html[data-motion="ready"] [data-reveal]{transition:none;transform:none}
}

/* ==========================================================================
   Corrections to the inherited layer
   ========================================================================== */

/* These three carry higher specificity than the rule above, so they have to
   be restated or they keep the italic. */
.features-section .features-heading h2 em,
.audience-section .section-heading h2 em,
.v113-outcomes .v113-outcome-heading h2 em{
  font-family:inherit;
  font-style:normal;
  font-weight:inherit;
  color:var(--indigo);
}

/* The inherited card tints landed on six different hues, several of them
   amber. Amber is the "needs a person" signal — it cannot also be decoration.
   All product surfaces are one paper; only semantic colour appears on them. */
.library-card,
.v113-outcomes .v112-product-card{
  background:var(--paper);
  border:1px solid var(--line);
}

/* --------------------------------------------------------------------------
   Hero proof. Real markup rather than pixels baked into a photograph, so the
   figures are selectable, legible to screen readers, and can resolve on cue.
   -------------------------------------------------------------------------- */
.hero-visual{position:relative}
.hero-figure{
  position:absolute;
  z-index:2;
  display:grid;
  gap:2px;
  margin:0;
  padding:14px 18px;
  border:1px solid var(--line);
  border-radius:12px;
  background:rgba(253,252,249,.92);
  backdrop-filter:blur(9px);
  box-shadow:0 18px 44px rgba(24,22,46,.10);
  white-space:nowrap;
}
.hero-figure-label{
  color:var(--quiet);
  font-size:10px;
  font-weight:600;
  letter-spacing:.09em;
  text-transform:uppercase;
}
.hero-figure strong{font-size:17px;font-weight:600;letter-spacing:-.02em}
.hero-figure strong b,
.hero-figure [data-hero-variance]{
  font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;
  font-weight:600;
}
.hero-figure--matched{top:14%;left:-4%}
.hero-figure--matched .hero-figure-rate{
  position:absolute;top:14px;right:18px;
  color:var(--green);font-family:var(--font-mono);font-size:11px;font-weight:600;
}
.hero-figure--matched strong{padding-right:52px}
.hero-figure--balance{bottom:12%;right:-2%}
.hero-figure--balance [data-hero-variance]{color:var(--indigo);font-size:26px}
.hero-figure-note{color:var(--quiet);font-size:11px}

html[data-motion="ready"] .hero-figure{opacity:0;animation:proof-in .8s var(--settle) forwards}
html[data-motion="ready"] .hero-figure--matched{animation-delay:.95s}
html[data-motion="ready"] .hero-figure--balance{animation-delay:1.25s}
@keyframes proof-in{from{opacity:0;transform:translateY(12px) scale(.97)}to{opacity:1;transform:none}}

@media (max-width:820px){
  .hero-figure--matched{top:4%;left:0}
  .hero-figure--balance{bottom:2%;right:0}
  .hero-figure{padding:11px 14px}
  .hero-figure strong{font-size:15px}
  .hero-figure--balance [data-hero-variance]{font-size:21px}
}
@media (prefers-reduced-motion:reduce){
  html[data-motion="ready"] .hero-figure{animation:none;opacity:1}
}

/* The tone classes carry more specificity than the base card rule, so they
   need naming explicitly. One paper for every product surface. */
.library-card,
.library-card.tone-lilac,
.library-card.tone-sage,
.v113-outcomes .v112-product-card{
  background:var(--paper);
}

/* A third surface value gives the page a quieter register to drop into,
   rather than a seventh variation on the same two tones. */
.faq-section{background:var(--paper-soft)}

/* ==========================================================================
   Audience — rebuilt
   ==========================================================================
   Was two flat full-width rows split into name | detail | a cramped 132px
   action column, with a large dead field down the middle. The content is a
   genuine binary — a firm running many client books, a business running its
   own — so the design is now that contrast: two equal panels, side by side.
   -------------------------------------------------------------------------- */

.audience-ledger{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:22px;
  margin-top:60px;
  border-top:0;
  border-bottom:0;
}
.audience-row,
.audience-row+.audience-row{
  display:flex;
  flex-direction:column;
  min-height:0;
  padding:42px 38px 34px;
  border:1px solid var(--line);
  border-radius:22px;
  background:var(--paper);
  transition:transform .5s var(--ease),box-shadow .5s var(--ease),border-color .4s ease;
}
.audience-row:hover,
.audience-row.is-business:hover{
  transform:translateY(-4px);
  box-shadow:0 26px 60px rgba(24,22,46,.09);
  border-color:rgba(35,122,87,.24);
  background:var(--paper);
}
.audience-name,.audience-detail,.audience-action{padding:0;border-left:0}

.audience-name>span{color:var(--quiet);font-size:12px;letter-spacing:-.005em}
.audience-name h3{
  margin:14px 0 0;
  font-size:clamp(32px,3.1vw,46px);
  font-weight:400;
  line-height:1;
  letter-spacing:-.026em;
}
.audience-name strong{margin-top:12px;font-size:12.5px;font-weight:600;letter-spacing:.01em}

.audience-detail{
  margin-top:26px;
  padding-top:26px;
  border-top:1px solid var(--line);
}
.audience-detail h4{font-size:20px;font-weight:600;line-height:1.28}
.audience-detail>p{margin-top:13px;color:var(--muted);font-size:14.5px;line-height:1.62}
.audience-detail ul{gap:9px;margin-top:22px}
.audience-detail li{
  padding:5px 11px 5px 20px;
  border:1px solid var(--line);
  border-radius:99px;
  color:var(--muted);
  font-size:12px;
}
.audience-detail li:before{left:10px;top:11px;width:5px;height:5px}

.audience-action{
  display:flex;
  align-items:center;
  gap:9px;
  margin-top:auto;
  padding-top:30px;
  color:var(--indigo);
  font-size:13.5px;
  font-weight:600;
}
.audience-row.is-business .audience-action{color:var(--green)}
.audience-action i{
  display:grid;
  place-items:center;
  width:26px;height:26px;
  border:1px solid currentColor;
  border-radius:50%;
  font-style:normal;
  transition:transform .4s var(--ease);
}
.audience-row:hover .audience-action i{transform:translate(3px,-3px)}

@media (max-width:900px){
  .audience-ledger{grid-template-columns:1fr;gap:16px}
  .audience-row,.audience-row+.audience-row{padding:34px 26px 28px}
}

/* The inherited CTA was 9px, capped at 115px wide, and stacked vertically —
   so it wrapped mid-phrase and read as a caption rather than an action. */
.audience-action{
  flex-direction:row;
  justify-content:flex-start;
  align-items:center;
  min-height:0;
  grid-column:auto;
  border-top:0;
}
.audience-action>span{
  max-width:none;
  color:inherit;
  font-size:13.5px;
  font-weight:600;
  line-height:1.3;
  white-space:nowrap;
}
.audience-action>i{
  width:28px;height:28px;
  color:currentColor;
  background:transparent;
  border:1px solid currentColor;
  font-size:12px;
  transform:none;
}
.audience-row:hover .audience-action>i{
  color:var(--paper);
  background:currentColor;
  transform:translate(3px,-3px);
}
.audience-row:hover .audience-action>i{color:#FDFCF9}

/* Monospace gives every glyph the same advance, so "." and "," open up gaps at
   display sizes ("13 . 2"). Tighten the large figures until the punctuation
   closes, without crowding the digits. */
[data-close-rate],[data-runway],[data-attention],[data-arr],
[data-bank-prepared],[data-ending-balance],[data-ledger-variance],
[data-recon-variance],[data-agent-confidence],[data-hero-variance],
.v112-focus-amount,.ledger-balance{
  letter-spacing:-.055em;
}
[data-ending-balance],[data-hero-variance]{letter-spacing:-.062em}

/* ==========================================================================
   Accessibility corrections
   ==========================================================================
   The inherited layer set supporting copy as small as 7.5px and used greys
   down to 2.47:1. Text below 11px is not readable; text below 4.5:1 is not
   accessible. Both are fixed at the source rather than case by case.
   -------------------------------------------------------------------------- */

.announcement span{font-size:11px;letter-spacing:.08em}
.announcement strong{font-size:11.5px}
.announcement b{font-size:11px}
.ledger-number{font-size:11px}
.hero-figure-label{font-size:11px}
.hero-figure-note{font-size:11.5px;color:var(--quiet)}
.hero-figure strong{color:var(--ink)}
.hero-figure--matched .hero-figure-rate{font-size:11.5px}

/* Product-card microcopy sat between 8.5px and 10px throughout. */
.library-copy p{font-size:14px;line-height:1.55;color:var(--muted)}
.audience-detail li{font-size:12px}

/* The closing CTAs sat in a grid whose row stretched the primary button to
   170px tall on narrow screens. A column of self-sized buttons instead. */
@media (max-width:820px){
  .closing-actions{
    display:flex;
    flex-direction:column;
    align-items:stretch;
    gap:10px;
    margin-top:26px;
  }
  .closing-actions .button{
    width:100%;
    min-height:52px;
    padding:0 20px;
    justify-content:center;
  }
}

/* ==========================================================================
   Root cause: unsized inline SVG
   ==========================================================================
   Inline <svg> with no width/height and no intrinsic ratio fills its
   container. Inside the closing CTA that made the arrow 174x174, which is
   what squeezed the label to min-content and wrapped "Book / a / demo" on
   desktop, and blew the button up to 176px tall on mobile. Size every inline
   icon so it can never claim the box.
   -------------------------------------------------------------------------- */
.button svg,
.button-large svg{
  width:1.05em;
  height:1.05em;
  flex:0 0 auto;
  fill:none;
  stroke:currentColor;
  stroke-width:1.7;
  stroke-linecap:round;
  stroke-linejoin:round;
}

/* The footer ran at 9px end to end. */
.site-footer{font-size:13px}
.site-footer nav strong{
  display:block;
  margin-bottom:12px;
  color:var(--ink);
  font-size:12px;
  font-weight:600;
  letter-spacing:.06em;
  text-transform:uppercase;
}
.site-footer nav a{display:block;padding:3px 0;color:var(--muted);font-size:13.5px}
.site-footer nav a:hover{color:var(--indigo)}
.site-footer>div>div>p{color:var(--muted);font-size:13.5px;line-height:1.6}
.footer-bottom{font-size:12.5px;color:var(--quiet)}
.footer-bottom span{font-size:12.5px}

/* Real content that was set below readable size. The finance-stack map is
   the page's actual integration story, not a mockup — it has to be legible. */
.v122-quadrant header span{font-size:13px;font-weight:600;letter-spacing:.02em}
.v122-quadrant header small{font-size:12px;color:var(--quiet)}
.v122-core-steps span{font-size:12px}
.v122-map-note{font-size:12.5px;color:var(--quiet)}
.v122-stack-map header small,
.zen-integrations header small{font-size:12px}
.faq-intro a span{font-size:13.5px;font-weight:600}
.closing-inner>small{font-size:12.5px;color:var(--quiet)}
.closing-balance small{font-size:12px;color:var(--quiet)}

/* The hero micro-list (a real content list, distinct from the figures above). */
.hero-proof{font-size:12.5px;color:var(--muted);gap:20px}
.hero-proof i{color:var(--green)}

/* Outcome card step markers and stack-map labels are content, not chrome. */
.v112-step{font-size:12px;font-weight:600;letter-spacing:.06em}
.v122-map-meta span{font-size:12.5px;font-weight:600}
.v122-core small{font-size:12px}
.v122-core>div>small{font-size:12px;color:var(--quiet)}

/* ==========================================================================
   The hero photograph
   ==========================================================================
   The photograph carries the page. It is left whole on purpose: cutting the
   stones out of it loses the contact shadows between them and the ambient
   shadow beneath, and the stack stops reading as something physically at
   rest. It arrives settling and then breathes.
   -------------------------------------------------------------------------- */
.hero-visual{position:relative}
.hero-visual-image{position:relative;z-index:1}

html[data-motion="ready"] .hero-visual-image{
  animation:stones-settle 1.5s var(--settle) both,
            hero-float 10s var(--ease) 1.7s infinite;
}
@keyframes stones-settle{
  from{opacity:0;transform:translateY(-26px) scale(.975)}
  to  {opacity:1;transform:none}
}

.hero-figure--balance{bottom:6%;right:-7%}
.hero-figure--balance [data-hero-variance]{color:var(--indigo);font-size:26px}

@media (prefers-reduced-motion:reduce){
  html[data-motion="ready"] .hero-visual-image{animation:none;opacity:1;transform:none}
}
/* ==========================================================================
   The hero stack
   ==========================================================================
   The four stones are the real ones, cut out of the photograph and
   reassembled at their measured positions. Because each is now its own
   element the stack can actually settle: they arrive from above, base first,
   and come to rest. The material is still photographic; the physics are real.
   -------------------------------------------------------------------------- */
.hero-visual{position:relative}
.hero-stones{
  position:relative;
  z-index:1;
  /* A concrete width, not a percentage: the stones are absolutely positioned
     with percentage widths, and this sits inside a place-items:center grid
     whose track is content-sized — so a percentage here resolves against
     nothing and the whole stack collapses to zero. */
  width:clamp(240px,27vw,400px);
  margin-inline:auto;
}
.hero-stones .stone{
  /* the hero settles on load, not on scroll */
  transform:none;
  transition:none;
  filter:drop-shadow(0 16px 26px rgba(20,18,44,.20));
}

html[data-motion="ready"] .hero-stones .stone{
  opacity:0;
  animation:stone-arrive 1.15s var(--settle) forwards;
  /* --i counts up from the base, so the stack builds upward */
  animation-delay:calc(.24s + var(--i) * .14s);
}
@keyframes stone-arrive{
  from{opacity:0;transform:translateY(-36px) rotate(calc(var(--tilt) * .6deg)) scale(.97)}
  to  {opacity:1;transform:none}
}

/* Once settled, the whole stack breathes — barely. */
html[data-motion="ready"] .hero-stones{animation:stack-breathe 11s var(--ease) 2.2s infinite}
@keyframes stack-breathe{
  0%,100%{transform:translateY(0)}
  50%    {transform:translateY(-7px)}
}

.hero-figure--matched{top:12%;left:-6%}
.hero-figure--balance{bottom:9%;right:-3%}
.hero-figure--balance [data-hero-variance]{color:var(--indigo);font-size:26px}

@media (prefers-reduced-motion:reduce){
  html[data-motion="ready"] .hero-stones,
  html[data-motion="ready"] .hero-stones .stone{animation:none;opacity:1;transform:none}
}

/* The headline carries its own line break after "Accounting work," — size it
   so that break is the one that happens, instead of orphaning "AI." */
.hero h1{
  max-width:none;
  font-size:clamp(38px,4.15vw,60px);
  line-height:.97;
  letter-spacing:-.045em;
}

/* Clear of the stones and of the bank-feed card baked into the photograph. */
/* Mirrors the bank-feed card baked into the photo: matched on the left,
   balanced on the right, the stones between them. */
.hero-figure--balance{top:auto;bottom:13%;right:0}

.hero-proof{gap:14px 24px}

/* --------------------------------------------------------------------------
   Hero parallax. Driven by --pointer-x / --pointer-y (-0.5 … 0.5), set by
   app.js. Applied to the containers so the photograph keeps its own
   settle-and-float animation.
   -------------------------------------------------------------------------- */
.hero{--pointer-x:0;--pointer-y:0}

.hero-parallax{
  transform:translate3d(calc(var(--pointer-x) * 26px),calc(var(--pointer-y) * 18px),0);
  transition:transform .5s cubic-bezier(.22,1,.36,1);
  will-change:transform;
}
/* The card drifts against the stones — the parallax that reads as depth. */
.hero-figure--balance{
  transform:translate3d(calc(var(--pointer-x) * -16px),calc(var(--pointer-y) * -11px),0);
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
/* Light moves across the stack with the pointer. */
.hero-glow{
  transform:translate3d(calc(var(--pointer-x) * 60px),calc(var(--pointer-y) * 40px),0);
  transition:transform .8s cubic-bezier(.22,1,.36,1);
}


/* The act rail is interactive, so it has to look and behave like it. */

@media (prefers-reduced-motion:reduce){
  .hero-parallax,.hero-figure--balance,.hero-glow{transform:none;transition:none}
}

/* --------------------------------------------------------------------------
   Partner wordmarks
   --------------------------------------------------------------------------
   These were twelve hotlinked logo files from Wikimedia and vendor CDNs. Any
   one of them failing left a broken image in the middle of the integrations
   map, and re-serving another company's logo file from your own page is not
   something to ship. Set as type: always renders, nothing to license.
   Swap in licence-cleared SVGs here if you obtain them.
   -------------------------------------------------------------------------- */
.v129-brand{
  font-family:var(--font-sans);
  font-size:15px;
  font-weight:600;
  letter-spacing:-.022em;
  color:var(--muted);
  white-space:nowrap;
  transition:color .35s var(--ease);
}
.v129-brand:hover{color:var(--ink)}
.v129-brand-row{gap:26px}

@media (max-width:900px){
  .v129-brand{font-size:13.5px}
  .v129-brand-row{gap:16px}
}

/* ==========================================================================
   Opening
   ==========================================================================
   The first two seconds are the whole first impression. Rather than every
   hero element fading in together, the page arrives in the order a person
   reads it: chrome, then the claim, then the proof, then the way in.

   Each line of the headline is masked and rises from beneath its own baseline,
   which is why the markup nests a span inside .hero-line.
   -------------------------------------------------------------------------- */

.hero-line{display:block;overflow:hidden;padding-bottom:.06em}
.hero-line>span{display:block}

html[data-motion="ready"] .hero-line>span{
  transform:translateY(105%);
  animation:line-rise 1s var(--settle) forwards;
}
html[data-motion="ready"] .hero-line:nth-child(1)>span{animation-delay:.26s}
html[data-motion="ready"] .hero-line:nth-child(2)>span{animation-delay:.38s}
@keyframes line-rise{to{transform:translateY(0)}}

/* The rest of the hero follows the headline in reading order. */
html[data-motion="ready"] .hero .announcement,
html[data-motion="ready"] .hero-copy>p,
html[data-motion="ready"] .hero-actions,
html[data-motion="ready"] .hero-proof,
html[data-motion="ready"] .hero-rail{
  opacity:0;
  animation:hero-in .85s var(--settle) forwards;
}
html[data-motion="ready"] .hero .announcement{animation-delay:.12s}
html[data-motion="ready"] .hero-copy>p  {animation-delay:.62s}
html[data-motion="ready"] .hero-actions {animation-delay:.74s}
html[data-motion="ready"] .hero-proof   {animation-delay:.86s}
html[data-motion="ready"] .hero-rail    {animation-delay:1.02s}
@keyframes hero-in{from{opacity:0;transform:translateY(13px)}to{opacity:1;transform:none}}

/* The nav settles in first — it is chrome, not content. */
html[data-motion="ready"] .nav-shell{
  animation:nav-in .8s var(--settle) both;
}
@keyframes nav-in{from{opacity:0;transform:translateY(-14px)}to{opacity:1;transform:none}}

/* The hero copy block is choreographed line by line, so it must not also be
   faded in wholesale by the generic reveal system. */
html[data-motion="ready"] .hero-copy[data-reveal],
html[data-motion="ready"] .hero-visual[data-reveal]{opacity:1;transform:none;transition:none}

@media (prefers-reduced-motion:reduce){
  html[data-motion="ready"] .hero-line>span,
  html[data-motion="ready"] .nav-shell,
  html[data-motion="ready"] .hero .announcement,
  html[data-motion="ready"] .hero-copy>p,
  html[data-motion="ready"] .hero-actions,
  html[data-motion="ready"] .hero-proof,
  html[data-motion="ready"] .hero-rail{animation:none;opacity:1;transform:none}
}

/* --------------------------------------------------------------------------
   Hero balance. The photograph was forced to 720px, which left the copy
   column at 502px and broke the headline across three lines. Give the words
   the larger share; the stack still reads at 600.
   -------------------------------------------------------------------------- */
@media (min-width:1121px){
  .hero-shell{grid-template-columns:1.18fr .82fr;gap:64px}
  .hero-visual-image{width:600px}
}

/* ==========================================================================
   FAQ
   ==========================================================================
   The heading column was narrow enough to break the sentence over four
   lines, and the answers sat lighter and smaller than the rest of the page's
   body copy.
   -------------------------------------------------------------------------- */
@media (min-width:981px){
  .faq-layout{grid-template-columns:360px minmax(0,1fr);gap:72px}
}
.faq-intro h2{font-size:clamp(28px,2.7vw,40px);max-width:14ch}
.faq-intro>p{margin-top:16px;color:var(--muted);font-size:14.5px;line-height:1.62;max-width:34ch}

.faq-item summary{padding:22px 0;font-size:16px;font-weight:600;letter-spacing:-.014em}
.faq-item p,.faq-answer,.faq-item [class*="answer"]{
  color:var(--muted);
  font-size:14.5px;
  line-height:1.68;
  max-width:68ch;
}
.faq-item{transition:background .35s var(--ease)}

/* ==========================================================================
   Closing
   ==========================================================================
   The payoff figure is the same one the sequence resolves to, so it carries
   the same colour. The card also had a wide dead field down its middle.
   -------------------------------------------------------------------------- */
.closing-inner [data-ending-balance]{color:var(--indigo)}
.closing-balance>span,.closing-balance small{color:var(--quiet)}

@media (min-width:981px){
  /* column-gap only — a shorthand `gap` here also spaces every row of the
     left-hand column apart, which pulls the card open down its middle. */
  .closing-inner{grid-template-columns:minmax(0,1fr) 380px;column-gap:64px;row-gap:0}
}
.closing-inner h2{max-width:16ch}
.closing-inner>p{max-width:46ch;font-size:15px;line-height:1.62;color:var(--muted)}

/* The closing card carried a leftover green cast on one edge. */
.closing-inner{
  background:
    radial-gradient(120% 130% at 88% 18%,rgba(29,27,196,.07),transparent 58%),
    var(--paper);
}

/* --------------------------------------------------------------------------
   Hero plate
   --------------------------------------------------------------------------
   This used to be a crop rig. The old source was a screenshot of an earlier
   build: the stones sat in one corner at x460-713 of 713, a bank-feed card and
   a stray figure shared the frame, and the base stone was cut off by the
   bottom edge. Showing it needed a window at x416-713, y196-490, the image
   blown to 240% and pushed to -140%/-69.5% to sit inside that window, and a
   gradient mask to fade the cut base into the paper. Six numbers, every one of
   them a compensation for a source that was never meant to be artwork.

   The source is now a real cut-out of the six-stone stack: keyed, centred in
   its own frame, whole, and trimmed by tools/plate.py to an equal margin so it
   centres itself. There is nothing to crop around, so all of it is gone.

   Height, not width, sets the scale — the stack is portrait (846x1490) and the
   hero column is limited by how tall it can be, not how wide.
   -------------------------------------------------------------------------- */
.hero-crop{
  position:relative;
  display:grid;
  justify-items:center;
  width:auto;
  aspect-ratio:auto;
  overflow:visible;
  margin-inline:auto;
}
.hero-crop .hero-visual-image{
  position:relative;
  left:auto;
  top:auto;
  width:auto;
  max-width:100%;
  height:clamp(259px,27vw,360px);
  /* Both inherited devices have to be turned off by name. styles.css carries a
     radial mask cut for the old 720px plate, which bites into the stones here,
     and a multiply that never fired anyway — .hero-parallax carries a
     transform, which opens a stacking context, so there was no backdrop to
     multiply against. The plate is keyed and already graded; it needs neither. */
  -webkit-mask-image:none;
          mask-image:none;
  mix-blend-mode:normal;
  filter:none;
}

/* ==========================================================================
   Audience — the two panels differ by structure, not by a colour token
   ==========================================================================
   A firm keeps many books shallow; a business keeps one book deep. Both
   panels previously said that in words and looked identical. Now the shape
   says it first: fourteen small stacks against one tall one, drawn from the
   same three-stone mark the brand is already built from.
   -------------------------------------------------------------------------- */

.aud-figure{
  display:flex;
  align-items:flex-end;
  flex-wrap:wrap;          /* never widen the panel it sits in */
  gap:9px;
  height:74px;
  margin-bottom:26px;
  overflow:hidden;
}
.aud-stack{
  position:relative;
  display:block;
  width:20px;
  height:26px;
  flex:0 0 auto;
  font-style:normal;
}
.aud-stack b{
  position:absolute;
  left:50%;
  translate:-50% 0;
  height:3px;
  border-radius:99px;
  background:var(--quiet);
  transition:background .45s var(--ease),translate .5s var(--settle);
  transition-delay:calc(var(--n,0) * 26ms);
}
.aud-stack b:nth-child(1){width:18px;bottom:2px}
.aud-stack b:nth-child(2){width:13px;bottom:8px}
.aud-stack b:nth-child(3){width:8px;bottom:14px;background:var(--indigo)}

/* Many books, shallow — the stacks step in height so the row reads as a
   portfolio rather than a fence. */
.aud-figure--many .aud-stack:nth-child(3n){height:22px}
.aud-figure--many .aud-stack:nth-child(4n){height:30px}

/* One book, deep. */
.aud-stack--deep{width:44px;height:74px}
.aud-stack--deep b{height:5px}
.aud-stack--deep b:nth-child(1){width:42px;bottom:2px}
.aud-stack--deep b:nth-child(2){width:36px;bottom:12px}
.aud-stack--deep b:nth-child(3){width:29px;bottom:22px;background:var(--quiet)}
.aud-stack--deep b:nth-child(4){width:22px;bottom:32px;background:var(--quiet)}
.aud-stack--deep b:nth-child(5){width:15px;bottom:42px;background:var(--quiet)}
.aud-stack--deep b:nth-child(6){width:9px;bottom:52px;background:var(--indigo)}

/* On approach the stacks settle — the same idea as everything else here. */
.audience-row:hover .aud-stack b{background:var(--ink)}
.audience-row:hover .aud-stack b:last-child{background:var(--indigo)}
.audience-row.is-business:hover .aud-stack b:last-child{background:var(--green)}
.audience-row:hover .aud-figure--many .aud-stack b{translate:-50% -2px}

@media (max-width:900px){
  .aud-figure{height:56px;gap:7px;margin-bottom:20px}
  .aud-figure--many .aud-stack:nth-child(n+11){display:none}
}
/* Ten stacks still outrun a 292px panel once its padding is counted. */
@media (max-width:560px){
  .aud-figure{gap:6px;height:48px}
  .aud-stack{width:17px}
  .aud-stack b:nth-child(1){width:15px}
  .aud-stack b:nth-child(2){width:11px}
  .aud-stack b:nth-child(3){width:7px}
  .aud-figure--many .aud-stack:nth-child(n+9){display:none}
}
@media (prefers-reduced-motion:reduce){
  .aud-stack b{transition:none}
}

/* ==========================================================================
   The mark settles
   ==========================================================================
   The three-stone glyph appears in every section label and in the brand mark,
   and until now it was completely inert — three absolutely-positioned bars
   with no transition and no response to anything. It is the one device the
   page already repeats everywhere, so it is the right carrier for the page's
   single idea: each mark arrives out of true and comes level as its section
   is reached.

   Driven by --settle (0 out of true, 1 level) set per-mark by app.js.
   Ships at 1, so with no JavaScript every mark is simply level.
   -------------------------------------------------------------------------- */

.label-stones,
.brand-mark:not(.v130-core-brand-mark){--settle:1}

.label-stones i,
.brand-mark:not(.v130-core-brand-mark) i{
  /* --off is the stone's own displacement when out of true; it scales to
     nothing as the mark settles. */
  transform:translateX(calc(-50% + var(--off,0px) * (1 - var(--settle))))
            rotate(calc(var(--tip,0deg) * (1 - var(--settle))));
  transition:transform .85s var(--settle-ease,cubic-bezier(.16,1.06,.32,1));
}
.label-stones i:nth-child(1),
.brand-mark i:nth-child(1){--off:3px;--tip:-4deg;transition-delay:0ms}
.label-stones i:nth-child(2),
.brand-mark i:nth-child(2){--off:-5px;--tip:5deg;transition-delay:70ms}
.label-stones i:nth-child(3),
.brand-mark i:nth-child(3){--off:4px;--tip:-6deg;transition-delay:140ms}

@media (prefers-reduced-motion:reduce){
  .label-stones i,
  .brand-mark i{transform:translateX(-50%);transition:none}
}

/* ==========================================================================
   Closing — the figure becomes the picture
   ==========================================================================
   The page's payoff figure was set at 52px in a side column, which is a
   caption, not a climax. Nowhere on the page did type reach a scale anyone
   would remember. Here it does: $0.00 is the largest object on the page, and
   the sentence that earns it sits underneath at reading size.

   This is the one place the accent runs at full bleed, so the page ends on
   the colour it took from the stone.
   -------------------------------------------------------------------------- */

.closing-section{padding:0}

.closing-inner{
  /* The figure leads; the sentence that earns it follows. In source order the
     balance block is last, so the composition is set here rather than by
     moving markup the reveal system and the counter both depend on. */
  display:flex;
  flex-direction:column;
  min-height:0;
  width:min(100% - 96px,var(--content));
  margin:0 auto;
  padding:104px 0 96px;
  border:0;
  border-radius:0;
  background:none;
  box-shadow:none;
  text-align:center;
}

.closing-inner .section-label{justify-content:center;margin:0 auto;order:1}
.closing-inner .closing-balance{order:2}
.closing-inner h2{order:3}
.closing-inner>p{order:4}
.closing-inner .closing-actions{order:5}
.closing-inner>small{order:6}

/* The figure. Tabular so it cannot shift, tight so it reads as one object. */
.closing-balance{
  display:block;
  margin:34px 0 0;
  padding:0;
  border:0;
  background:none;
  text-align:center;
}
/* The sub-copy repeated the section above it; the label stays as a caption. */
.closing-balance small{display:none}
/* The first span repeats the section eyebrow directly above it; the second
   is the figure's caption and stays. */
.closing-balance>span:nth-of-type(1){display:none}
.closing-balance>span{
  display:block;
  margin-top:14px;
  color:var(--quiet);
  font-size:12px;
  font-weight:600;
  letter-spacing:.1em;
  text-transform:uppercase;
}
.closing-balance>span i{display:none}

.closing-inner [data-ending-balance]{
  display:block;
  font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;
  /* Sized so the string itself fits, not just its box: "$0.00" in Plex Mono
     runs about 4.8x the font size, so a floor of 84px overflowed a 356px
     column by 47px and pushed the whole page sideways. */
  font-size:clamp(52px,16vw,264px);
  font-weight:600;
  line-height:.86;
  letter-spacing:-.062em;
  color:var(--indigo);
}

.closing-inner h2{
  max-width:none;
  margin:18px auto 0;
  font-size:clamp(30px,4vw,58px);
}
.closing-inner>p{
  max-width:46ch;
  margin:20px auto 0;
}
.closing-actions{justify-content:center;margin-top:34px}
.closing-inner>small{display:block;margin:22px auto 0;text-align:center}

/* A rule beneath the figure, doubled — an accountant reads a double rule as a
   closed total without needing to be told. */
.closing-balance::after{
  content:"";
  display:block;
  width:min(100%,760px);
  height:4px;
  margin:26px auto 0;
  border-top:1px solid var(--line-strong);
  border-bottom:1px solid var(--line-strong);
}

@media (max-width:760px){
  .closing-inner{width:calc(100% - 34px);padding:76px 0 68px}
  .closing-actions{flex-direction:column;align-items:stretch}
}

/* ==========================================================================
   Figures inside the product previews
   ==========================================================================
   Monospace gives "." and "," a full character cell, so "$0.00" sets as
   "$0 . 00". At the display sizes above, negative tracking closes that up.
   Inside the card previews it cannot: those figures sit next to labels at
   9-13px, and tracking tight enough to close the punctuation crowds the
   digits into each other.

   Instrument Sans measures its digits tabular already — 1111 and 0000 are the
   same width to the tenth of a pixel — so the columns still line up and the
   figures still don't reflow while they animate. It is also what a real
   ledger interface is set in. Mono stays where it is a specimen rather than
   a readout: the hero variance, the sequence, the closing figure.
   ========================================================================== */
.library-preview [data-agent-confidence],
.library-preview [data-ledger-variance],
.library-preview [data-bank-prepared],
.library-preview [data-recon-variance],
.library-preview [data-recon-rate],
.library-preview [data-close-rate],
.library-preview [data-runway],
.library-preview [data-arr],
.library-preview [data-attention],
.library-preview [data-progress],
.library-preview .ledger-number,
.library-preview .close-meter b,
.library-preview .ledger-balance,
.library-preview .bank-amount,
.library-preview .match-amount,
.library-preview .report-row b,
.library-preview .forecast-value{
  font-family:var(--font-sans);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
  letter-spacing:-.018em;
}

/* ==========================================================================
   The floor under exposed type, properly enforced
   ==========================================================================
   The audit that cleared this page walked leaf elements only, so every
   element that mixes a child with its own text was invisible to it — which
   is every `.section-label`, because they all carry a stone mark. Those
   kickers were setting at 9px, and so were the hero rail, the stack footer
   and two links. Nine-pixel uppercase is a habit, not a decision: it costs
   the reader and buys nothing the page could not get from weight and colour.

   Nothing exposed to a reader now sets below 11.5px.
   ========================================================================== */
.section-label{font-size:11.5px;letter-spacing:.115em}
.hero-rail span{font-size:11.5px;letter-spacing:.085em}
.v122-section-foot span{font-size:12px}
.v122-map-meta a{font-size:12px}
.faq-intro a{font-size:12.5px}
.announcement{font-size:12px}
.announcement span{font-size:11.5px;letter-spacing:.09em}
.hero-figure-label{font-size:11.5px}
.hero-figure-note{font-size:12px}
.announcement b{font-size:11.5px}

/* ==========================================================================
   Word gaps, and one more mono chip
   ==========================================================================
   Instrument Sans sets its word space near .18em, narrow for the face. Above
   ~13px that reads as tight and confident; below it the gap drops under two
   rendered pixels and words fuse — "ready for review" arrives as "readyfor
   review". A third of a point back, everywhere the sans is doing the work.
   Newsreader has a wider space of its own and does not want the help.
   ========================================================================== */
body{word-spacing:.035em}
h1,h2,h3,h4,
.hero h1,.audience-name h3,.faq-section h2{word-spacing:normal}

/* The hero chip is an interface element, not a specimen. In mono its "$0.00"
   sets as "$0 . 00" — the same full-cell punctuation the previews had, and at
   26px it is the most visible instance of it on the page. The sequence
   readout and the closing figure stay in mono: there the mechanical rhythm is
   the point, and at 34px+ the tracking already closes the gaps. */
.hero-figure strong b,
.hero-figure [data-hero-variance]{
  font-family:var(--font-sans);
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
  letter-spacing:-.028em;
  font-weight:600;
}

/* The rail the section kickers sit in was cut for 9px type. At 11.5px
   "Who Zenday is for" needs about 145px and was breaking to three lines with
   an orphan. Widen the rail and let it break evenly. */
.section-heading,.features-heading{grid-template-columns:138px minmax(0,1fr) 292px}
.section-heading>.section-label,
.features-heading>.section-label{align-items:flex-start;line-height:1.5;text-wrap:balance}
.section-heading>.section-label .label-stones,
.features-heading>.section-label .label-stones{margin-top:3px}
@media (max-width:1180px){
  .section-heading,.features-heading{grid-template-columns:124px minmax(0,1fr) 250px}
}
@media (max-width:980px){
  .section-heading,.features-heading{grid-template-columns:1fr}
}

/* --------------------------------------------------------------------------
   The stack across the breakpoints. Heights now, for the same reason as above.
   At 820 the hero goes single-column and the stack has width to grow into.
   -------------------------------------------------------------------------- */
/* All four breakpoints live here and nowhere else. A second
   @media (max-width:1120px) rule for this same selector had been appended
   further down the file; media queries add no specificity, so source order
   decided, and the later 1120 rule was overriding the 820 and 560 rules at
   every width below 820 — both were dead, and every narrow viewport was
   clamping to the desktop rule's floor instead. Same selector, same property,
   one place. */
@media (max-width:1120px){ .hero-crop .hero-visual-image{height:clamp(240px,29vw,328px)} }
@media (max-width:820px) { .hero-crop .hero-visual-image{height:min(52vw,300px)} }
@media (max-width:560px) { .hero-crop .hero-visual-image{height:min(64vw,250px)} }

/* The balance chip is positioned in percentages of its containing block. That
   used to be a box the width of the whole column, so at the stack's real size
   the chip drifted away from it. Anchor the chip to the plate instead. */
.hero-visual{display:grid;place-items:center}
.hero-anchor{position:relative;display:grid;justify-items:center}
.hero-figure--balance{bottom:-6%;right:-30%}
@media (max-width:820px){ .hero-figure--balance{bottom:-4%;right:-16%} }
@media (max-width:560px){ .hero-figure--balance{bottom:-2%;right:-8%} }

/* The glow was a 500x440 indigo blur sized to sit behind a 720px plate. Behind
   a 302px one it spills well past every edge, and the plate's opaque ground
   covers the middle of it — which draws exactly the rectangle the plate no
   longer has. The stack does not need a halo; it has its own contact shadow. */
.hero-glow{display:none}

/* The chip beside the stack, not on top of it. */
.hero-figure--balance{bottom:7%;right:-38%}
@media (max-width:820px){ .hero-figure--balance{bottom:2%;right:-22%} }
@media (max-width:560px){ .hero-figure--balance{bottom:0;right:-10%} }

/* --------------------------------------------------------------------------
   The hero chip
   --------------------------------------------------------------------------
   Three versions of this. It said "Unexplained variance · $0.00", which is a
   fact about bookkeeping rather than about this product. Then it said what the
   agents had counted, which was right about the AI and wrong about the
   photograph: a running total competes with a stack of stones instead of
   completing it.

   It is now the smallest thing it can be and says the two things the stones
   are already saying — the agents are running, and the month is at rest. A
   status, not a statistic.
   -------------------------------------------------------------------------- */

.hero-figure--balance{
  display:grid;
  gap:4px;
  /* Sized against the plate, not in isolation. The sans that replaced the
     display serif is wider at the same point size, which took this card to
     191px — wider than the 204px stack it annotates, and at the narrow
     breakpoints wider than the stack outright. A label cannot be bigger than
     its subject. */
  padding:10px 14px 11px;
  white-space:nowrap;
}
.hero-live{
  display:flex;
  align-items:center;
  gap:7px;
  color:var(--indigo-deep);
  font-size:10px;
  font-weight:650;
  letter-spacing:.09em;
  text-transform:uppercase;
}
.hero-live>i{
  width:6px;height:6px;
  border-radius:50%;
  background:var(--indigo);
  box-shadow:0 0 0 3px rgba(29,27,196,.14);
}
@media (prefers-reduced-motion:no-preference){
  /* A slow pulse, well under the three-flashes-a-second threshold and with no
     luminance jump — it reads as "running", not as an alert. */
  .hero-live>i{animation:agent-pulse 2.8s var(--ease) infinite}
  @keyframes agent-pulse{
    0%,100%{box-shadow:0 0 0 3px rgba(29,27,196,.14)}
    50%{box-shadow:0 0 0 6px rgba(29,27,196,.06)}
  }
}
.hero-state{
  font-family:var(--font-display);
  font-optical-sizing:auto;
  font-size:16px;
  /* Was italic for the serif. Only the upright Instrument Sans file is
     loaded, so italic here would be a browser-synthesised slant. */
  font-style:normal;
  font-weight:400;
  letter-spacing:-.014em;
  color:var(--ink);
}

/* --------------------------------------------------------------------------
   The plate's own placement, now that it is portrait
   --------------------------------------------------------------------------
   Three things were tuned for the old landscape crop and are wrong for a tall
   stack.

   The float keyframes in styles.css carry translateX(-2%) in every frame — a
   nudge that used to re-centre a plate whose subject sat off to one side. The
   new plate is trimmed to an equal margin, so it is already centred and the
   nudge just pulls it 6px left of its column. Redefining the keyframes here
   (same name, later in the cascade) drops the X and keeps the breathing.

   The stack is also smaller than the room it has at the middle breakpoint,
   where the hero is still two columns but the viewport has stopped giving
   34vw enough to work with.
   -------------------------------------------------------------------------- */
@keyframes hero-float{
  0%,100%{transform:translateY(0)}
  50%    {transform:translateY(-4px)}
}

/* The chip, against a portrait stack -----------------------------------------
   At the old placement (bottom 7%, right -38%) the chip landed across the
   middle of the base stone — the widest, darkest thing on the page — and read
   as a sticker on top of the photograph rather than a card in front of it.
   Dropped to the stack's foot and pushed out past its edge, it overlaps only
   the lower-right curve, which is what gives the depth without hiding the
   subject.

   --chip-out is how far the chip reaches past the stack's right edge. It is a
   px value because the chip has a fixed width, so the overlap wanted is a px
   quantity, not a proportion — and it grows at the narrow breakpoints because
   the stack shrinks there while the chip does not. Swept and measured against
   the plate's own alpha rather than eyeballed: the chip hides 2-3% of the
   stack at every breakpoint from 1440 to 360, with no horizontal scroll and
   no collision with the hero rail.

   It is also capped by the viewport, which is the constraint that actually
   bites and the one .hero{overflow:hidden} hides rather than reports: at the
   value the overlap alone wanted, the chip ran 18px off the right edge at
   360px wide and was silently cut in half. Every breakpoint now ends inside
   the viewport with margin to spare. */
.hero-figure--balance{bottom:-1%;right:calc(-1 * var(--chip-out));--chip-out:120px}
@media (max-width:1120px){ .hero-figure--balance{bottom:-1%;--chip-out:130px} }
@media (max-width:820px) { .hero-figure--balance{bottom:0;--chip-out:130px} }
/* At 560 the chip stops fitting beside the stack: 161px of card against a
   182px stone, hanging 11px into the hero rail below it. Measured, not
   eyeballed — see tools note in the commit. It gets smaller here and sits
   inside the plate's foot rather than below it. */
/* At 560 the chip stops being placeable beside the stack at all. The plate is
   142px wide there and the card is 153px — wider than its own subject — so
   every offset that keeps it inside the viewport buries 9% or more of the
   stones, and every offset that clears the stones runs off the screen. Swept
   the full range and there is no value that satisfies both.

   So it stops being an overlay and becomes a caption. .hero-anchor is already
   a centred grid, so dropping the absolute positioning puts the chip in the
   second row, under the stack, centred to it — which is what a label that
   cannot fit beside its subject should do anyway. */
@media (max-width:560px){
  .hero-figure--balance{
    position:static;
    inset:auto;
    margin-top:15px;
    padding:9px 13px 10px;
    gap:3px;
  }
  .hero-figure--balance .hero-live{font-size:9.5px;gap:6px}
  .hero-figure--balance .hero-state{font-size:15px}
}

/* <picture> wraps the plate so the browser can take AVIF (75KB) or WebP
   (119KB) instead of the 786KB PNG fallback. display:contents keeps the <img>
   itself as the grid item, so every rule above still addresses what it did. */
.hero-crop picture{display:contents}

/* ==========================================================================
   The product card, rebuilt: paper with a window cut through it
   ==========================================================================
   The cards read as eight identical white boxes, and the measurements say
   exactly why. The rule above flattens every card to --paper (252). The
   section behind them is --paper-soft (227). And the fragments inside each
   card carry their OWN paper surfaces — .ui-obj, .ui-pair, .ui-ask are all
   var(--paper) with a hairline. So the object sat six values off the ground
   it was supposed to be sitting on. Six values is not a surface, it is a
   rounding error, and the eye reads the whole card as one flat field with
   some grey marks floating in the lower half.

   The fix is not another tint. Three pastel card fills were tried before this
   (tone-lilac, tone-sage, and a plain third) and they were removed because
   nothing decided WHICH card got which — a decorative device that encodes
   nothing reads as noise, and they are still flattened by the rule above.

   Instead the card gets structure. It is paper, and a window is cut through
   it down to the ground the section is painted in, and the fragment sits in
   that window. Now there are three real planes — card 252, window 227,
   fragment 252 again with its hairline — so the interface reads as an object
   resting IN something rather than printed ON nothing. The window is the
   section's own colour, which is what makes it read as cut rather than as a
   second card stacked on the first.
   ========================================================================== */

.library-card{
  border-radius:20px;
  box-shadow:0 1px 2px rgba(24,22,46,.035),0 16px 40px rgba(24,22,46,.045);
}

.library-preview{
  /* Was margin-top:auto, which pinned each window to the bottom of its card
     and left every window a different height across a row. Filling the
     remaining space instead equalises them, and .ui already centres its own
     content, so short fragments sit in the middle of their window rather
     than being padded out with air. */
  flex:1 1 auto;
  display:grid;
  align-content:center;
  margin:0 20px 20px;
  padding:20px 18px;
  border-radius:13px;
  overflow:hidden;
}

/* The bottom fade belonged to the old previews, which were tall screenshots
   cropped mid-row. The fragments are content-sized now, so there is no cut to
   disguise — and the fade was painting to --paper over a --paper-soft window,
   which put a pale band across the bottom of all eight. */
.library-preview::after{display:none}

/* The two lead cards open the section, so their window carries a trace of
   indigo — the only thing separating them from the six below is that they are
   about the agents themselves. Hierarchy, not decoration. */
@media (min-width:1180px){
  .library-card:nth-child(1) .library-preview,
  .library-card:nth-child(2) .library-preview{
    margin:0 26px 26px;
    background:none;
  }
}
@media (max-width:620px){
  .library-preview{margin:0 16px 16px;padding:16px 14px}
}

/* Hover: the card lifts, and the window deepens with it. */
.library-card:hover /* The window this fragment used to sit in is gone — see .library-preview
   above. Two framed surfaces around one object is what made these read as
   diagrams mounted on a card rather than as software. */
@media (prefers-reduced-motion:reduce){
  .library-card:hover .library-preview{transform:none}
}

/* ==========================================================================
   The card chrome comes off
   ==========================================================================
   Measured against the reference: what reads as "clean" there is not a
   treatment applied to cards, it is the absence of cards. Their features sit
   in a flat grid divided by hairlines — no border, no radius, no shadow, no
   tint, no hover lift. The rule and the whitespace do all of the separating,
   which leaves the mockup as the only object in the cell with any weight.

   Ours had a 19px radius, a border, a 54px drop shadow, a tinted background
   on two of the eight, and a translateY on hover. Five devices to say "these
   are separate things", when a 1px line says it and gets out of the way.

   The heading follows the same logic: an h3 at 23px over a 14.5px paragraph
   is two type sizes and a gap where one sentence would do. It is one
   paragraph now, at reading size, with the name of the module in ink at the
   front and the explanation in grey behind it — so the eye lands on the
   mockup rather than on a headline.
   -------------------------------------------------------------------------- */

.feature-grid{
  column-gap:0;
  row-gap:0;
  border-top:1px solid var(--line);
}
.library-card{
  min-height:0;
  border:0;
  border-radius:0;
  background:none;
  box-shadow:none;
  border-bottom:1px solid var(--line);
  border-right:1px solid var(--line);
  padding:clamp(26px,2.4vw,38px) clamp(22px,2vw,32px);
  transition:background .35s var(--ease);
}
.library-card.tone-lilac,
.library-card.tone-sage{background:none}
.library-card:hover{transform:none;box-shadow:none;border-color:var(--line);background:rgba(29,27,196,.014)}
.library-card:hover:after{opacity:0}
.library-card:after{display:none}

/* the rightmost cell in a row has no rule to its right */
@media (min-width:1180px){
  .library-card:nth-child(2),
  .library-card:nth-child(5),
  .library-card:nth-child(8){border-right:0}
}
@media (min-width:900px) and (max-width:1179px){
  .library-card:nth-child(even){border-right:0}
}
@media (max-width:899px){
  .library-card{border-right:0}
}

/* one paragraph, module name in ink, explanation behind it */
.library-card-header,
.library-card:nth-child(1) .library-card-header,
.library-card:nth-child(2) .library-card-header{
  min-height:0;
  /* right padding clears the ↗ that sits over the corner: without it the
     sentence ran under the link on every card whose copy reached three lines */
  padding:0 44px clamp(18px,1.8vw,26px) 0;
}
/* Every card, including the first two. Those carried their own 29px and 34px
   overrides from when they were the wide hero cards of the grid — with one
   type size for the whole set, two cards shouting is just two cards shouting. */
.library-card-header h3,
.library-card:nth-child(1) .library-card-header h3,
.library-card:nth-child(2) .library-card-header h3{
  display:inline;
  max-width:none;margin:0;
  font-size:clamp(16px,1.25vw,18.5px);
  font-weight:640;line-height:1.5;letter-spacing:-.017em;
}
.library-card-header h3:after{content:"."}
.library-card-header p,
.library-card:nth-child(1) .library-card-header p,
.library-card:nth-child(2) .library-card-header p{
  display:inline;
  max-width:none;margin:0 0 0 .34em;
  color:var(--quiet);
  font-size:clamp(16px,1.25vw,18.5px);
  font-weight:400;line-height:1.5;letter-spacing:-.011em;
}
/* Aligned to the first line of the sentence, not to a card corner that no
   longer exists — it was landing halfway down the paragraph. */
.library-card-header>a{
  position:absolute;top:clamp(25px,2.35vw,37px);right:clamp(22px,2vw,32px);
  width:26px;height:26px;font-size:12px;
  border-color:rgba(23,22,28,.075);background:none;
}
.library-card:hover .library-card-header>a{color:var(--indigo);border-color:rgba(29,27,196,.22)}

/* the fragment is the only object in the cell */
.library-preview{margin:0;padding:0}

/* The ring was sized for a card with a 460px floor. In a grid cell scaled to
   its content it was the largest object in the section and outweighed three
   tables. */
.ui-ring{width:118px;height:118px}
.ui-ring strong{font-size:27px}
.ui-ring small{font-size:12px}

/* --------------------------------------------------------------------------
   The feature grid, as one thing
   --------------------------------------------------------------------------
   Built card by card, the section stopped being a section: mockups ranging
   209 to 354 pixels tall, one row 540 and the next 688, and paragraphs long
   enough to compete with the screens they were meant to introduce.

   Rows are equalised so the grid stops stepping, and every window reserves
   the same band so the fragments read as one family rather than eight
   unrelated pictures. The copy is cut to two lines because on this section
   the screen is the argument and the sentence only points at it.
   -------------------------------------------------------------------------- */
/* Equal rows was the wrong lever: it made the two wide cards in row one
   inherit the tallest row's height and open a void under their mockups. The
   band on the window is what actually equalises the fragments; rows can size
   to their own content, because the hairline grid already aligns them. */
.library-card{display:flex; flex-direction:column}
.library-card-header p{text-wrap:pretty}
.library-preview{min-height:var(--win,300px); align-content:center}

@media (max-width:1180px){ .library-preview{--win:280px} }
@media (max-width:899px){
  .feature-grid{grid-auto-rows:auto}
  .library-preview{--win:0}
}

/* --------------------------------------------------------------------------
   Give the cards their titles back
   --------------------------------------------------------------------------
   The bold-lead sentence — title and description set inline at one size,
   separated only by weight — reads well on a page with three of them. On
   eight it stops reading as eight titles and starts reading as one long
   grey column, which is exactly what "everything feels like a big page"
   describes: nothing to look at first.

   So the title steps up and out onto its own line, and the description
   steps down and quiet beneath it. Eight anchors down the section instead
   of eight sentences.
   -------------------------------------------------------------------------- */
.library-card-header h3,
.library-card:nth-child(1) .library-card-header h3,
.library-card:nth-child(2) .library-card-header h3{
  display:block;
  margin:0 0 7px;
  font-size:clamp(19px,1.55vw,23px);
  font-weight:660;
  line-height:1.22;
  letter-spacing:-.026em;
  color:var(--ink);
}
.library-card-header h3:after{content:none}

.library-card-header p,
.library-card:nth-child(1) .library-card-header p,
.library-card:nth-child(2) .library-card-header p{
  display:block;
  margin:0;
  max-width:42ch;
  font-size:clamp(14px,1.02vw,15.5px);
  font-weight:400;
  line-height:1.55;
  letter-spacing:-.006em;
  color:var(--quiet);
}

/* the two wide cards lead the section, so their titles lead the row */
.library-card:nth-child(1) .library-card-header h3,
.library-card:nth-child(2) .library-card-header h3{
  font-size:clamp(21px,1.85vw,27px);
}

/* The header reserved 44px on the right while the arrow occupies 56 at its
   largest, so six of the eight descriptions ran under it. It clears now, and
   the arrow sits level with the title rather than beside the sentence. */
.library-card-header{padding-right:62px}
/* the two wide cards carry their own padding rules at higher specificity, so
   the clearance has to be stated at their level or it never reaches them */
.library-card:nth-child(1) .library-card-header,
.library-card:nth-child(2) .library-card-header{padding-right:66px}
.library-card-header>a{top:clamp(24px,2.2vw,34px)}
.library-card:nth-child(1) .library-card-header>a,
.library-card:nth-child(2) .library-card-header>a{top:clamp(30px,2.8vw,40px)}
