/* ============================================================================
   Fascia & Ledger — shared design system (source: Anvul Home.html).
   Linked by the homepage (Anvul Home.html), the signup wizard
   (web/onboarding/), the Founder/Domain console (Anvul HQ.html), and the
   Firm console (Anvul Platform.html) — each links this FIRST, then loads its
   own sheet(s) after to re-point the console token NAMES onto this warm paper
   /Bricolage/Spline identity while its structural layout wins.

   The single source of truth for the terracotta "Ink & Signal" brand:
   the paper/ink token palette, the fixed 9-tier type scale, the three
   font voices (Bricolage fascia · Hanken body · Spline mono clerk), and
   the reusable primitives — the CLAUSE, THE SUM (audited double-rule),
   the FASCIA guarantee-board, THE WALL course, and the STRUCK-PLATE
   buttons. Consumer-agnostic: NO page-specific IDs, wrappers, or layout.
   A consumer needs only to <link> this one file (the @import below pulls
   the three families; adding the <link rel="stylesheet"> for the same URL
   is also fine and marginally faster).

   Extracted faithfully from Anvul Home.html's <style> block so every
   primitive renders byte-identically. Do NOT diverge the tokens/primitives
   here from the homepage without reconciling both.
   ========================================================================== */

/* Fascia & Ledger — 3 variable files replace ~9 static instances (LIGHTER):
   Bricolage gains the condensed wdth axis (the fascia cut, display-only);
   Hanken's variable range makes body 430 render TRUE (not snapped to 500);
   Spline Sans Mono is the one clerk's voice for labels + ALL money. */
@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wdth,wght@12..96,75..100,200..800&family=Hanken+Grotesk:wght@300..800&family=Spline+Sans+Mono:wght@400;600&display=swap");

/* ---------- TOKENS ---------- */
:root{
  --paper:#f4f2ec; --paper-deep:#efece3; --paper-deeper:#e9e5da;
  --card:#fbf9f3; --card-lift:#ffffff;
  --ink:#1c1b19; --ink-2:#5d574c; --ink-3:#857d70;
  --line:rgba(28,27,25,.12); --line-strong:rgba(28,27,25,.20); --line-soft:rgba(28,27,25,.07);
  --terra:#c75b39; --terra-text:#a8472b; --terra-deep:#9c4127; --terra-bright:#e8916f;
  --terra-tint:rgba(199,91,57,.08); --terra-tint-2:rgba(199,91,57,.14);
  /* THE SIGNAL — the hard-hat's own safety-orange (sampled from the founder's
     mark). Codified so it is used NOWHERE else: the mark alone wears it;
     everything else speaks terracotta. */
  --signal:#fc6415;
  --cream:#fdfbf6; --ok:#2f7d57; --ok-tint:rgba(47,125,87,.12);
  /* dark surface tokens (on-brand, for the contrast sections) */
  --void:#151412; --void-2:#1f1d1a; --void-line:rgba(253,251,246,.10);
  /* THE WALL tile — running bond at whisper strength: the winner surface
     reads as BUILT; low enough that ink/ink-2 text stays AA on it */
  --brick:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='142' height='58'%3E%3Cg fill='%23c75b39' fill-opacity='.05'%3E%3Crect x='0' y='0' width='68' height='26'/%3E%3Crect x='71' y='0' width='68' height='26'/%3E%3Crect x='-35.5' y='29' width='68' height='26'/%3E%3Crect x='35.5' y='29' width='68' height='26'/%3E%3Crect x='106.5' y='29' width='68' height='26'/%3E%3C/g%3E%3C/svg%3E");
  --display:"Bricolage Grotesque",system-ui,sans-serif;
  --sans:"Hanken Grotesk",system-ui,-apple-system,sans-serif;
  --mono:"Spline Sans Mono",ui-monospace,"SF Mono",Menlo,Consolas,"Roboto Mono",monospace;
  /* Fascia & Ledger — THE fixed type scale. Nothing else is permitted; the
     deliberate size-void between 1.5rem and 1.75rem IS the hierarchy
     (Bricolage may only ever appear at or above 1.75rem). */
  --t-display:clamp(2.6rem,1.2rem + 6.8vw,5.5rem);
  --t-h2:clamp(2rem,1.1rem + 3.8vw,3.4rem);
  --t-h3:clamp(1.25rem,1.05rem + .9vw,1.5rem);
  --t-lead:clamp(1.0625rem,1rem + .5vw,1.25rem);
  --t-body:1rem;
  --t-small:.875rem;
  --t-caption:.8125rem;
  --t-label:.6875rem;
  --t-money:clamp(2.75rem,2.1rem + 2.8vw,4.25rem);
  /* the Ruled Page — where the terracotta margin rule falls (mobile: inside
     the 18px content margin; desktop: hanging just left of the content column).
     Consumed by the opt-in .ruled helper below. */
  --rule-x:max(14px,calc(50vw - 582px));
  --shadow-soft:0 1px 2px rgba(28,27,25,.04), 0 8px 24px rgba(28,27,25,.06);
  --shadow-lift:0 2px 4px rgba(28,27,25,.05), 0 18px 44px rgba(28,27,25,.12);
  --shadow-tall:0 4px 8px rgba(28,27,25,.06), 0 40px 80px -22px rgba(28,27,25,.24);
  --shadow-ring:0 0 0 1px var(--line), var(--shadow-soft);
  --r-xl:26px; --r-lg:22px; --r-md:16px; --r-sm:11px;
  --maxw:1180px;
  --ease:cubic-bezier(.2,.7,.3,1); --ease-out:cubic-bezier(.16,1,.3,1);
}

/* ---------- BASE VOICE ----------
   The homepage sets these on <body>. A consumer may apply them at the root
   or scope them to its own chrome wrapper; the treatments are what matter. */
body{
  font-family:var(--sans); color:var(--ink); background:var(--paper);
  line-height:1.6; -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  /* 430 renders TRUE — Hanken is loaded as a variable range (300..800), so
     this no longer snaps to 500 the way discrete weights did */
  font-weight:430;font-synthesis:none;
}
/* …and emphasis finally bites */
b,strong{font-weight:650}
/* the fascia (display) voice — condensed Bricolage, >=1.75rem sizes ONLY */
h1,h2{font-family:var(--display);font-weight:780;font-stretch:82%;line-height:.98;letter-spacing:-.01em;text-wrap:balance;font-feature-settings:"ss01" on,"liga" on}
/* below the size-void, headings speak Hanken */
h3,h4{font-family:var(--sans);font-weight:700;line-height:1.2;letter-spacing:-.012em;text-wrap:balance}
h3{font-size:var(--t-h3)}
:focus-visible{outline:2.5px solid var(--terra);outline-offset:3px;border-radius:6px}
::selection{background:var(--terra);color:#fff}

/* ---------- SHARED PRIMITIVES ---------- */
/* the CLAUSE — a mono clause number hung on the margin rule ("01 / THE
   COMPARISON"); a short terracotta tick that crosses the rule. This replaces
   the centred-eyebrow template everywhere.
   Mobile: the tick COPES the number — a short terracotta rule sits directly
   above the clause number, both flush on the gutter (un-clipped). Desktop
   (>=720px, where a margin rule exists) reverts to the reach-back tick.
   --ctx = the tick's resting translateX, shared by the base + the reveal so
   one transform rule serves both placements. */
.clause{
  --ctx:0px;
  font-family:var(--mono);font-weight:600;font-size:var(--t-label);letter-spacing:.12em;
  text-transform:uppercase;color:var(--terra-text);display:inline-flex;align-items:center;
  position:relative;margin-bottom:14px;
  /* clearance for the coping tick sitting above the number (mobile) */
  margin-top:9px;
}
.clause::before{content:"";position:absolute;left:0;bottom:100%;margin-bottom:7px;width:28px;height:2px;background:var(--terra);transform:translateX(var(--ctx))}
@media(min-width:720px){
  /* the rule is back — the tick reaches across it, on the number's own line;
     the coping clearance is not needed (the tick shares the number's line) */
  .clause{--ctx:-4px;margin-top:0}
  .clause::before{left:auto;right:100%;bottom:auto;top:calc(50% - 1px);margin-bottom:0;width:30px}
}

/* THE SUM — money as audited bookkeeping: the clerk's mono, tabular figures;
   a TOTAL takes a hairline above and the double rule beneath (the 500-year-old
   "this number is audited" mark). */
.sum{font-family:var(--mono);font-variant-numeric:tabular-nums lining-nums}
.sum-total{border-top:1px solid var(--line-strong);border-bottom:3px double var(--ink)}
span.sum-total{display:inline-block;padding:.08em .06em .14em;line-height:1.2}
/* on dark surfaces the double rule is struck in the light ink — opt in by
   placing .sum-total inside a .on-dark region (or add .on-dark to it directly).
   (On the homepage this is bound to the specific dark cards; here it is a
   generic, consumer-agnostic helper with the identical result.) */
.on-dark .sum-total,.sum-total.on-dark{border-top-color:rgba(253,251,246,.3);border-bottom-color:var(--cream)}

/* hairline engineering grid — the quiet "we build software" tell */
.rule{height:1px;background:linear-gradient(90deg,transparent,var(--line),transparent);border:0}

/* the clerk's small caps label — a mono key/eyebrow (not money) */
.kbd{font-family:var(--mono);font-size:var(--t-label);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);font-weight:600}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}

/* THE FASCIA GUARANTEE-BOARD — one recurring signboard (the sign above the
   shop door): slender ink strip, signwriter's cream mono caps, painted
   end-rules. It CONSOLIDATES guarantee chip rows into one board; recurs
   identically beneath primary CTAs. Markup: .fascia-board > .fb-line
   (with .fb-dot separators). */
.fascia-board{
  width:100%;max-width:420px;margin:14px auto 0;position:relative;
  background:linear-gradient(180deg,#2a2723,#1b1a17 55%,#151412);
  padding:.72em 1.05em .78em;text-align:center;
  box-shadow:0 2px 6px rgba(28,27,25,.22),inset 0 1px 0 rgba(255,236,214,.12),inset 0 -2px 0 rgba(0,0,0,.4);
}
.fascia-board::before{content:"";position:absolute;inset:5px 7px;border:1px solid rgba(244,238,224,.2);pointer-events:none}
.fascia-board .fb-line{
  font-family:var(--mono);font-weight:600;font-size:var(--t-label);
  letter-spacing:.13em;text-transform:uppercase;color:#e9e3d4;
  line-height:1.9;text-wrap:balance;
}
.fascia-board .fb-dot{color:#cf7c58}

/* THE WALL — a single course of running-bond brick that replaces a structural
   hairline at the strongest beats. Terracotta bricks, paper mortar, hand-cut
   edges. Markup: .wall-course > svg (the brick pattern). Under the opt-in
   motion layer below the course LAYS ITSELF left-to-right once; with no JS /
   reduced motion the course stands complete. */
.wall-course{position:relative;height:24px;background:var(--paper-deep);overflow:hidden}
.wall-course svg{display:block;width:100%;height:24px}
.wall-course+section{border-top:none}

/* ---------- BUTTONS — the STRUCK PLATE: the 999px SaaS pill is retired.
     Squared 3px plate, a signwriter's rule inside the edge (the fascia-board's
     own inset border), a weighted scale(.975) press. --mgx/--mgy = an optional
     JS-lerped magnetic pull (pointer-fine only); the 0px defaults keep this
     byte-identical when no motion JS is present. ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  font-family:var(--sans);font-weight:600;font-size:var(--t-body);
  padding:0 1.4em;min-height:52px;border-radius:3px;cursor:pointer;border:none;
  transition:transform .16s var(--ease),box-shadow .18s,background .18s,border-color .18s;
  white-space:nowrap;text-align:center;text-decoration:none;position:relative;isolation:isolate;
  -webkit-tap-highlight-color:transparent;user-select:none;
}
.btn-primary{background:var(--terra);color:#fff;box-shadow:0 2px 6px rgba(156,65,39,.28), inset 0 1px 0 rgba(255,255,255,.2)}
.btn-primary::before{content:"";position:absolute;inset:3px;border:1px solid rgba(255,255,255,.28);border-radius:1px;pointer-events:none}
.btn-primary::after{content:"";position:absolute;inset:0;border-radius:inherit;background:linear-gradient(180deg,rgba(255,255,255,.16),transparent 42%);z-index:-1;opacity:.9}
.btn-primary:active{background:var(--terra-deep);transform:scale(.975);box-shadow:0 1px 3px rgba(156,65,39,.3), inset 0 1px 0 rgba(255,255,255,.2)}
.btn-ghost{background:var(--card-lift);color:var(--ink);border:1.5px solid var(--line-strong);box-shadow:var(--shadow-soft)}
.btn-ghost:active{border-color:var(--ink);transform:scale(.975)}
.btn-ink{background:var(--ink);color:var(--cream);box-shadow:inset 0 0 0 1px rgba(253,251,246,.16)}
.btn-ink:active{background:#000;transform:scale(.975)}
.btn .arr{transition:transform .18s var(--ease)}
/* hover motion is a pointer-device luxury; touch gets the press states above */
@media(hover:hover) and (pointer:fine){
  .btn-primary:hover{background:var(--terra-deep);transform:translate(var(--mgx,0px),calc(var(--mgy,0px) - 2px));box-shadow:0 12px 28px rgba(156,65,39,.36), inset 0 1px 0 rgba(255,255,255,.2)}
  .btn-ghost:hover{border-color:var(--ink);transform:translateY(-2px);box-shadow:var(--shadow-lift)}
  .btn-ink:hover{background:#000;transform:translateY(-2px);box-shadow:0 12px 28px -10px rgba(0,0,0,.5)}
  .btn:hover .arr{transform:translateX(4px)}
}
/* the struck ripple contained to the plate (matches the homepage) */
.btn-primary{overflow:hidden}

/* ---------- OPT-IN: THE RULED PAGE ----------
   One continuous terracotta margin rule down the whole surface, passing
   through light and dark alike; section heads (the .clause) hang off it.
   OPT IN by adding class="ruled" to the scrolling container (it must be
   position:relative; the homepage puts this on <body>). Desktop-only by
   design — at phone widths the rule reads as a stray line, so only the
   short clause ticks show there. */
.ruled{position:relative}
.ruled::after{
  content:"";position:absolute;top:0;bottom:0;left:var(--rule-x);width:1px;
  background:linear-gradient(180deg,rgba(199,91,57,0),rgba(199,91,57,.5) 150px,rgba(199,91,57,.5) calc(100% - 140px),rgba(199,91,57,0));
  pointer-events:none;z-index:5;display:none;
}
@media(min-width:720px){.ruled::after{display:block}}

/* ---------- OPT-IN: FORGED reveal (the Forge-Line motif) ----------
   The consumer-agnostic core of the homepage's motion layer. EVERY rule
   keys off html.fxon, which a tiny head script must set ONLY when JS +
   IntersectionObserver are live AND the visitor hasn't asked for reduced
   motion — so no-JS / reduced-motion / legacy visitors get the complete,
   truthful final state (the reduced-motion belt below is the second belt).

   Usage: add class="fx" to a section; the observer adds .seen when it
   scrolls in (and .seenh to strike a tall section's head early). Inside:
     .clause      — its tick strikes L->R, the clause number unmasks
     .cl-i        — a masked inline run that slides in (wrap in .cl-m)
     h2           — stands up 40ms after
     .fxi         — any child that rises in sequence (--i sets its stagger)
     .fx.hl       — a section whose top hairline draws in
   Transforms/opacity only. (Page-specific choreography — comparison ticks,
   the calculator instrument, the set-piece — stays on the homepage; only
   these reusable devices live here.) */
.cl-m{display:inline-block;overflow:hidden}
.fxon .fx .clause::before{transform:translateX(var(--ctx)) scaleX(0);transform-origin:0 50%;transition:transform .55s var(--ease-out)}
.fxon .fx.seen .clause::before,.fxon .fx.seenh .clause::before{transform:translateX(var(--ctx)) scaleX(1)}
.fxon .fx .cl-i{display:inline-block;transform:translateX(-103%);transition:transform .55s var(--ease-out)}
.fxon .fx.seen .cl-i,.fxon .fx.seenh .cl-i{transform:none}
.fxon .fx h2{opacity:0;transform:translateY(12px);transition:opacity .55s var(--ease-out) .04s,transform .55s var(--ease-out) .04s}
.fxon .fx.seen h2,.fxon .fx.seenh h2{opacity:1;transform:none}
.fxon .fx .fxi{opacity:0;transform:translateY(10px);transition:opacity .55s var(--ease-out),transform .55s var(--ease-out);transition-delay:calc(var(--i,0)*60ms)}
.fxon .fx.seen .fxi{opacity:1;transform:none}
/* a section whose top border draws in from the rule's side (swap the static
   border for a drawn line — same colour, same place) */
.fxon .fx.hl{border-top-color:transparent}
.fxon .fx.hl::before{content:"";position:absolute;top:-1px;left:0;right:0;height:1px;background:var(--line);transform:scaleX(0);transform-origin:0 50%;transition:transform .55s var(--ease-out)}
.fxon .fx.hl.seen::before,.fxon .fx.hl.seenh::before{transform:scaleX(1)}
/* THE WALL lays itself — a paper cover retreats off the bricks once */
.fxon .wall-course::after{content:"";position:absolute;inset:-1px;background:var(--paper-deep);transform-origin:100% 50%;transition:transform .9s var(--ease-out) .05s}
.fxon .wall-course.seen::after{transform:scaleX(0)}

/* the belt: reduced motion (and, via html.fxon gating, no-JS) = the finished,
   truthful state. This mirrors the homepage's reduced-motion block for the
   reusable devices exposed here. */
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto!important}
  html{scroll-behavior:auto}
  .fxon .fx .clause::before{transform:translateX(var(--ctx))!important}
  .fxon .fx .cl-i,.fxon .fx h2,.fxon .fx .fxi{opacity:1!important;transform:none!important}
  .fxon .fx.hl::before{transform:scaleX(1)!important}
  .fxon .wall-course::after{display:none}
}
