/* ==========================================================================
   Steady Scale — Home
   Sand & Forest design system · calm editorial (Wolverine-inspired)
   ========================================================================== */

:root {
  /* Palette */
  --sand:        #F5F0E6;
  --sand-2:      #EFE8DA;
  --surface:     #FDFBF6;
  --ink:         #2B2A26;
  --ink-soft:    #6A665B;
  --line:        #E3DAC8;
  --forest:      #2E4A3D;
  --forest-deep: #21382D;
  --forest-ink:  #1A2E25;
  --terracotta:  #D97B4A;
  --terracotta-deep: #BE6435;
  /* Terracotta Ink — the accent darkened for SMALL text on the Sand/Surface
     grounds. Terracotta Deep is only 3.65:1 on Sand and 4.01:1 on Surface;
     eyebrows and kickers are 0.72–0.74rem, so they need 4.5:1 to meet the
     WCAG 2.2 AA target PRODUCT.md commits to. This clears it at 4.89:1.
     Terracotta Deep stays the accent for rules, borders, and large text. */
  --terracotta-ink: #A5502A;
  --sage:        #8FA398;
  --sage-soft:   #E7EDE8;

  /* Logo tints for placeholders */
  --ph-1: #F3E8D6;
  --ph-2: #E7CFA9;
  --ph-3: #DCA875;

  /* Type */
  --font-serif: 'Lora', Georgia, 'Times New Roman', serif;
  --font-sans:  'Work Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;

  /* Rhythm */
  --container: 76rem;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --section-y: clamp(4rem, 9vw, 8rem);
  --radius: 6px;
  --radius-lg: 14px;

  --shadow-sm: 0 1px 2px rgba(43,42,38,.05);
  --shadow-md: 0 2px 6px rgba(43,42,38,.06), 0 14px 40px -18px rgba(43,42,38,.22);
  --ease: cubic-bezier(.4,0,.2,1);
}

/* ---------- Reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; }
h1, h2, h3, h4 { font-family: var(--font-serif); font-weight: 500; margin: 0; line-height: 1.12; letter-spacing: -.01em; text-wrap: balance; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 3px; border-radius: 2px; }

/* Same-page links land clear of the sticky header (4.75rem tall) instead of
   underneath it. Covers every section anchor on the marketing pages — #who,
   #services, #how, #pricing, #projects, #partnerships, #marketing, #sales,
   #technology, #operations. terms.css:25 does the same for clause headings. */
section[id] { scroll-margin-top: 6rem; }

/* Touch behaviour. `manipulation` drops the ~300ms wait browsers otherwise
   spend watching for a double-tap-to-zoom, so taps register immediately.
   The tap highlight is set explicitly because the default is a system blue
   that has nothing to do with this palette. */
a, button, .btn, summary, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(217, 123, 74, .18);
}

/* Skip link — parked offscreen until it takes focus, then pinned into view.
   A skip link that stays offscreen while focused is invisible to the sighted
   keyboard users it exists for, which is the one audience it has. */
.skip-link { position: absolute; left: -9999px; top: 0; z-index: 200; }
.skip-link:focus { left: var(--gutter); top: .75rem; }

.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- Shared bits ---------- */
.eyebrow {
  font-family: var(--font-sans);
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--terracotta-ink);
  margin: 0 0 1.1rem;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
}
.eyebrow::before {
  content: "";
  width: 1.6rem;
  height: 1px;
  background: var(--terracotta);
}
.section-title { font-size: clamp(1.9rem, 3.6vw, 2.9rem); }
.lead { font-size: 1.18rem; color: var(--ink-soft); max-width: 46ch; }

/* The house voice-of-customer device — a first-person line in real typographic
   quotes. Lora, italic, softer ink, smaller than the headline. This lives in
   the shared sheet on purpose: DESIGN.md requires it look identical on every
   page, and a per-page copy is exactly how that drifts apart. */
.voc {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.0625rem;
  color: var(--ink-soft);
}

/* Ruled rows — the house list treatment for inclusions and capabilities.
   Deliberately no check icons: a tick on every line is the saturated SaaS tell
   and carries no information the row doesn't already. */
.ruled-list li {
  font-size: .95rem;
  line-height: 1.5;
  padding: .65rem 0;
  border-bottom: 1px solid var(--line);
}
.ruled-list li:last-child { border-bottom: 0; }

/* ==========================================================================
   Secondary page scaffolding — shared by Pricing, Services, and any page that
   isn't the home hero. Lives here rather than per-page so the two don't drift.
   ========================================================================== */
.page-hero { padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(2.5rem, 5vw, 4rem); }
.page-hero h1 {
  /* Held below the home hero's 4.6rem display step: on a secondary page the
     content is the thing that should carry weight, not the title. */
  font-size: clamp(2.3rem, 5.4vw, 3.7rem);
  line-height: 1.06;
  margin: 0 0 1.1rem;
  max-width: 16ch;
}
.page-hero .sub { font-size: 1.18rem; color: var(--ink-soft); max-width: 54ch; text-wrap: pretty; }

/* Jump links — these pages are long and owners read them in a stolen moment.
   Deliberately not styled as buttons; they navigate, they don't convert. */
.jump-row {
  margin-top: 2.25rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 2rem;
}
.jump-row .arrow-link { min-height: 44px; } /* real tap targets, not inline text links */
.jump-row .arrow-link:hover .arw { transform: translateY(2px); }

.section--sand2 { background: var(--sand-2); }


/* Arrow link */
.arrow-link {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: .95rem;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--forest);
  transition: gap .2s var(--ease), color .2s var(--ease);
}
.arrow-link .arw { transition: transform .2s var(--ease); }
.arrow-link:hover { color: var(--terracotta-deep); gap: .7rem; }
.arrow-link:hover .arw { transform: translateX(3px); }

/* Buttons */
.btn {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .01em;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .85rem 1.4rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
  min-height: 44px;
}
.btn .arw { transition: transform .2s var(--ease); }
.btn:hover .arw { transform: translateX(3px); }
.btn--primary { background: var(--forest); color: #fff; }
.btn--primary:hover { background: var(--forest-deep); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--forest); color: var(--forest); }
.btn--on-dark { background: var(--sand); color: var(--forest-ink); }
.btn--on-dark:hover { background: #fff; }

/* Image placeholders (curated, clearly swappable) */
.media {
  position: relative;
  width: 100%; /* definite width so aspect-ratio + min-height can't force overflow */
  border-radius: var(--radius);
  overflow: hidden;
  background:
    linear-gradient(150deg, var(--ph-1) 0%, var(--ph-2) 55%, var(--ph-3) 100%);
  isolation: isolate;
}
.media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("assets/logos/logo-emblem.webp");
  background-repeat: no-repeat;
  background-position: 118% 128%;
  background-size: 62%;
  opacity: .16;
  mix-blend-mode: multiply;
  z-index: -1;
}
/* Real photography, once a slot is filled. The gradient beneath stays as the
   loading placeholder, so a lazy tile never flashes empty. */
.media__img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media__label {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  font-family: var(--font-sans);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--forest-ink);
  background: rgba(253,251,246,.82);
  border-radius: 999px;
  padding: .35rem .75rem;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  backdrop-filter: blur(2px);
}

/* Placeholder tint variants — vary tiles so photo slots don't read identical */
.media--sage { background: linear-gradient(150deg, #EAF0EB 0%, #C7D5CB 55%, #93AC9D 100%); }
.media--clay { background: linear-gradient(150deg, #F6E7DC 0%, #E8BE9F 55%, #C98A61 100%); }
.media--dawn { background: linear-gradient(150deg, #F5EDDD 0%, #E3CBA4 55%, #B9A379 100%); }

/* ==========================================================================
   Who we serve — photo mosaic
   ========================================================================== */
.mosaic-head { max-width: 60ch; margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.mosaic-head h2 { font-size: clamp(1.8rem, 3.6vw, 2.7rem); margin-bottom: .9rem; }
.mosaic-head .lead { margin: 0; }
.mosaic-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(2, 1fr);
  padding-bottom: 1.75rem; /* room for the offset tiles */
}
.mosaic-grid .media { aspect-ratio: 3 / 4; }
.mosaic-grid .media:nth-child(even) { transform: translateY(1.75rem); }
@media (min-width: 900px) {
  .mosaic-grid { grid-template-columns: repeat(4, 1fr); gap: 1.25rem; }
}
/* Scroll-driven drift. The tiles are visible from the start — there is no
   entrance. The motion is the scroll itself re-laying the mosaic: each tile
   travels a different distance as the section crosses the viewport, so the
   row's rhythm keeps shifting instead of arriving once and going static.
   The script writes `translate` (not `transform`) so the drift composes with
   the nth-child offset above rather than overwriting it.

   Deliberately no `will-change` here. The hero promotes a single layer, but
   this would pin four 896x1200-backed tiles into compositor memory for the
   life of the page, and owners browse on phones. `translate` is composited
   while it animates anyway, so the promotion buys very little for the cost. */

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(245,240,230,.85);
  backdrop-filter: saturate(120%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.site-header.is-scrolled { border-color: var(--line); background: rgba(245,240,230,.94); }
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 4.75rem;
}
.brand { display: inline-flex; align-items: center; flex: none; }
.brand img { height: 30px; width: auto; }
.brand:focus-visible { outline-offset: 6px; }

.nav { display: none; }
.nav ul { display: flex; align-items: center; gap: 2rem; }
.nav a {
  font-family: var(--font-sans);
  font-size: .95rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink);
  padding: .35rem 0;
  position: relative;
  transition: color .2s var(--ease);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--terracotta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .25s var(--ease);
}
.nav a:hover { color: var(--forest); }
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--forest); }

.header-cta { display: none; }

.menu-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
}
.menu-toggle span { display: block; height: 2px; width: 20px; margin-inline: auto; background: var(--ink); transition: transform .25s var(--ease), opacity .2s var(--ease); }
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile menu panel */
.mobile-nav {
  display: none;
  border-top: 1px solid var(--line);
  background: var(--sand);
  padding: 1rem var(--gutter) 1.5rem;
}
.mobile-nav.open { display: block; }
.mobile-nav ul { display: flex; flex-direction: column; gap: .25rem; }
.mobile-nav a {
  display: block;
  text-decoration: none;
  font-family: var(--font-sans);
  font-weight: 500;
  color: var(--ink);
  padding: .8rem .25rem;
  border-bottom: 1px solid var(--line);
}
.mobile-nav .btn { margin-top: 1rem; width: 100%; justify-content: center; }

@media (min-width: 900px) {
  .nav { display: block; }
  .header-cta { display: inline-flex; }
  .menu-toggle { display: none; }
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero { padding: clamp(3rem, 7vw, 6rem) 0 var(--section-y); }
.hero-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.hero-copy h1 {
  font-size: clamp(2.6rem, 6.4vw, 4.6rem);
  line-height: 1.04;
  margin: 0 0 1.4rem;
}
.hero-copy h1 .soft { color: var(--forest); }
.hero-copy .sub { font-size: 1.2rem; color: var(--ink-soft); max-width: 40ch; margin: 0 0 2rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; }
.hero-media { aspect-ratio: 4 / 5; min-height: 22rem; }
.hero-trust {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.5rem;
  font-size: .85rem;
  color: var(--ink-soft);
}
.hero-trust span { display: inline-flex; align-items: center; gap: .5rem; }
.hero-trust span::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--sage); }

@media (min-width: 860px) {
  .hero-grid { grid-template-columns: 1.05fr .95fr; }
}

/* ==========================================================================
   Problem (forest band)
   ========================================================================== */
.band-forest { background: var(--forest); color: #F4F1EA; }
.band-forest .eyebrow { color: #E4B48F; }
.band-forest .eyebrow::before { background: var(--terracotta); }
.section { padding: var(--section-y) 0; }

.problem-grid { display: grid; gap: clamp(1.5rem, 4vw, 3.5rem); }
.problem-quote {
  font-size: clamp(1.7rem, 3.4vw, 2.6rem);
  line-height: 1.16;
  color: #fff;
  max-width: 18ch;
}
.problem-body { display: flex; flex-direction: column; gap: 1.25rem; }
.problem-body p { color: #DAE2DB; font-size: 1.08rem; max-width: 54ch; }
.problem-body strong { color: #fff; font-weight: 600; }
@media (min-width: 820px) {
  .problem-grid { grid-template-columns: 1fr 1.25fr; align-items: start; }
}

/* ==========================================================================
   What we help with
   ========================================================================== */
.help-head { max-width: 60ch; margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.help-head h2 { font-size: clamp(1.8rem, 3.6vw, 2.7rem); margin-bottom: .9rem; }
.help-head .lead { margin: 0; }

.pillars { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
.pillar {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.75rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
.pillar:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: #D8CDB7; }
/* `html.has-reveal .reveal.in` (below) sets transform: none at specificity
   (0,3,1), which outranks .pillar:hover's (0,2,0) — so once a card has
   scrolled into view, hover's translateY silently loses and the card never
   lifts. Its transition shorthand (opacity/transform only, .7s) outranks
   ours the same way, so box-shadow/border-color would snap instead of ease.
   Both re-declared one class heavier than .reveal.in so hover keeps
   working, and keeps its own .25s timing, once the reveal has fired. Same
   fix as the .way cards below. */
html.has-reveal .pillar.reveal.in {
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
html.has-reveal .pillar.reveal.in:hover { transform: translateY(-4px); }

/* Icon well — the documented system component: 2.75rem square, 12px radius,
   Sage Soft fill, Forest line icon at 1.5rem. Shared so the pillar cards on
   home and the domain headings on the Services page stay one definition. */
.icon-well, .pillar__icon {
  width: 2.75rem; height: 2.75rem;
  flex: none;
  display: grid; place-items: center;
  border-radius: 12px;
  background: var(--sage-soft);
  color: var(--forest);
}
.icon-well svg, .pillar__icon svg { width: 1.5rem; height: 1.5rem; }
.pillar h3 { font-size: 1.3rem; }
.pillar p { font-size: .95rem; color: var(--ink-soft); }
.help-cta { margin-top: clamp(2rem, 4vw, 3rem); }

@media (min-width: 640px) { .pillars { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .pillars { grid-template-columns: repeat(4, 1fr); } }

/* ==========================================================================
   How we work
   ========================================================================== */
/* The copy sits above the panel now, not beside it — the confrontation needs the
   full container width, so there is no two-column grid here any more. */
.work-copy h2 { font-size: clamp(1.9rem, 3.8vw, 2.9rem); margin-bottom: 1.3rem; max-width: 16ch; }
.work-copy p { color: var(--ink-soft); margin-bottom: 1.1rem; max-width: 54ch; }
.work-copy strong { color: var(--ink); font-weight: 600; }
.compare {
  margin-top: 1.75rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* Direct children only: these are the two cells. A descendant selector here also
   catches anything nested inside a cell (the bars below), padding it like a cell. */
.compare > div { background: var(--surface); padding: 1.1rem 1.2rem; }
.compare .k { font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-soft); margin-bottom: .35rem; }
/* Tabular figures: these two amounts are read against each other, so the
   digits need to occupy identical widths or the comparison reads crooked. */
.compare .v { font-family: var(--font-serif); font-size: 1.15rem; color: var(--ink); line-height: 1.25; font-variant-numeric: tabular-nums; }
.compare .them .v { color: var(--ink-soft); }
.compare .us { background: var(--sage-soft); }
.compare .us .v { color: var(--forest); }
/* This section has no photograph, so the published figure anchors it. The
   comparison stacks rather than sitting side by side, so each number gets the
   full panel width instead of half. The 1px grid gap over the Line ground
   gives the hairline rule between them.
   The value size is capped at 1.8rem deliberately: the longest string here,
   "$2,500–$10,000+ / month", measures 349px at that size against 373px of
   available cell width at the tightest column. Going larger orphans "month"
   onto its own line, which reads as a broken price rather than a big one. */
.work-figure { margin: 0; }
/* Opposed panels — the section's argument, staged as a confrontation.
   The two sides stop sharing a ground: theirs is Forest Ink with the palette
   inverted (the treatment DESIGN.md specifies inside a Forest ground), ours is
   Surface. They butt together with no gap and no rule, so the tonal jump itself
   is the dividing line.
   This is a contained panel, NOT a Ground Band: it does not run full-bleed and
   does not mark a chapter break, so the two-to-three band budget is untouched. */
.compare--versus {
  margin-top: clamp(2.25rem, 5vw, 3.25rem);
  grid-template-columns: 1fr;
  gap: 0;
  background: none;
  border: 0;
}
/* Generous vertical padding is doing real work: at full container width the two
   halves read as squat unless they are given height to stand in. */
.compare--versus > div { padding: clamp(2rem, 4.6vw, 3.4rem) clamp(1.5rem, 3.4vw, 2.4rem); }
.compare--versus .them { background: var(--forest-ink); }
.compare--versus .us { background: var(--surface); }
.compare--versus .v {
  font-size: clamp(1.6rem, 3.6vw, 2.5rem);
  line-height: 1.12;
  text-wrap: balance;
}
/* The unit rides smaller and quieter so the figure itself lands first. */
.compare--versus .unit { font-size: .5em; letter-spacing: .01em; }
.compare--versus .them .v { color: #F4F1EA; }
.compare--versus .them .k { color: #A9BDB0; }
.compare--versus .them .unit { color: #A9BDB0; }
.compare--versus .us .v { color: var(--forest); }
/* The one Terracotta on this screen, on the side it is meant to point at.
   Terracotta Ink is the token reserved for small text on Surface (4.89:1). */
.compare--versus .us .k { color: var(--terracotta-ink); }
.compare--versus .us .unit { color: var(--ink-soft); }
@media (min-width: 760px) {
  .compare--versus { grid-template-columns: 1fr 1fr; }
}

/* The gap, drawn. Both cells carry identical padding, so the two tracks line up
   across the hairline and can be read against each other. One shared scale: the
   full track is $10,000 / month.
     them — 100% wide, because the agency range is open-ended. Ink Soft to the
            25% mark ($2,500, the floor they start at), lighter beyond, then
            fading out at the right edge, which is what the "+" actually means.
     us   — 4.95%. That is 495 against the same 10,000. The stub is the argument;
            the empty remainder of the track is the point being made.
   Bars are aria-hidden: the printed figures above them are the real data. */
.bar {
  height: 14px;
  margin-top: 1.05rem;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.bar__fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  transform-origin: left center;
}
/* Track = $10,000 / month. Both bars start at the left edge and their LENGTH is
   the figure: theirs is 75% for the $7,500 span of $2,500–$10,000, ours is
   4.95% for $495. */
.bar--them .bar__fill { width: 75%; }
.bar--us .bar__fill { width: 4.95%; }

/* Inverted inside the Forest Ink half: translucent light on the dark ground is
   the container treatment DESIGN.md already specifies for Forest grounds. */
/* The empty remainder of the track has to be legible, not merely present — it
   is what shows the bar as a measured length against a scale rather than a
   full-width fill. */
.compare--versus .them .bar { background: rgba(244,241,234,.22); }
/* Even tone the whole way: every point inside the range is equally theirs, and
   a segmented fill would imply a breakpoint the pricing does not have. Only the
   top end softens, which is the "+" — the range is open above $10,000. */
.compare--versus .bar--them .bar__fill {
  background: #F4F1EA; /* fallback where the gradient is unsupported */
  background: linear-gradient(to right, #F4F1EA 0 74%, rgba(244,241,234,.15) 100%);
}
.compare--versus .us .bar { background: var(--sage-soft); }
.compare--versus .bar--us .bar__fill { background: var(--forest); }
/* Stays Ink Soft: this annotates how to read the chart, so it sits below the
   figcaption in the hierarchy. Sized up from .76rem because owners skew 40+ and
   12px is tight — the tone carries the demotion, not the point size. */
.bar__scale {
  margin: .7rem 0 0;
  font-family: var(--font-sans);
  font-size: .82rem;
  color: var(--ink-soft);
}

/* Drawn on scroll by the page's existing .reveal trigger — no second observer.
   The default state is fully drawn, so with no JS, reduced motion, or a deep
   link the chart is simply there rather than gated behind a transition. */
/* Drawn by the panel's own observer, NOT by the page's .reveal class. .reveal
   carries a 2.5s safety net that adds .in to every element whether it has been
   scrolled to or not, so riding it meant the bars finished drawing long before
   anyone reached this section. `.bars-armed` is set by script, so no-JS and
   reduced-motion visitors never meet the collapsed state at all. */
.compare--versus.bars-armed .bar__fill { transform: scaleX(0); }
.compare--versus.bars-armed.bars-in .bar__fill {
  transform: scaleX(1);
  transition: transform 1.15s var(--ease);
}
/* The two bars move in character. Theirs is the slow one, still travelling when
   you have stopped watching it. Ours lands late and quick: short and settled. */
.compare--versus.bars-armed.bars-in .bar--us .bar__fill {
  transition-duration: .5s;
  transition-delay: .55s;
}
/* Charcoal Warm, not Ink Soft. This caption is now the only place the
   "published and fixed" promise appears in the section, so the Reading Floor
   Rule applies: it is content to be read, not a muted annotation. Ink Soft
   here measured 4.70:1, level with the documented floor; this clears it. */
.work-figure__note {
  margin: .9rem 0 0;
  font-family: var(--font-sans);
  font-size: .9rem;
  line-height: 1.5;
  color: var(--ink);
}

/* ==========================================================================
   Two ways to work
   ========================================================================== */
.ways-head { max-width: 54ch; margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.ways-head h2 { font-size: clamp(1.9rem, 3.8vw, 2.9rem); }
.ways { display: grid; gap: 1.5rem; grid-template-columns: 1fr; }
.way {
  position: relative;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  padding: clamp(1.75rem, 3vw, 2.5rem);
  display: flex;
  flex-direction: column;
  gap: 1rem;
  overflow: hidden;
  text-decoration: none; /* card is now an <a>; default underline would
                             otherwise bleed into every heading and paragraph */
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
/* Same lift used on the .pillar cards above, so both "clickable card"
   patterns on this page read as one motion language. */
.way:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: #D8CDB7; }
/* `html.has-reveal .reveal.in` (below) sets transform: none at specificity
   (0,3,1), which outranks .way:hover's (0,2,0) — so once a card has scrolled
   into view, hover's translateY silently loses and the card never lifts. Its
   transition shorthand (opacity/transform only, .7s) outranks ours the same
   way, so box-shadow/border-color would snap instead of ease. Both
   re-declared one class heavier than .reveal.in so hover keeps working, and
   keeps its own .25s timing, once the reveal has fired. */
html.has-reveal .way.reveal.in {
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
html.has-reveal .way.reveal.in:hover { transform: translateY(-4px); }
.way::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--terracotta);
}
.way__media {
  aspect-ratio: 16 / 7;
  border-radius: var(--radius);
  margin-bottom: .4rem;
}
.way .kicker {
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--terracotta-ink);
}
.way h3 { font-size: clamp(1.4rem, 2.6vw, 1.85rem); line-height: 1.2; max-width: 20ch; }
.way p { color: var(--ink-soft); }
.way .plans {
  margin-top: auto;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
.way .plans li {
  font-size: .82rem;
  font-weight: 500;
  color: var(--forest);
  background: var(--sage-soft);
  border-radius: 999px;
  padding: .35rem .8rem;
}
.ways-cta { margin-top: clamp(2rem, 4vw, 3rem); text-align: center; }
@media (min-width: 820px) { .ways { grid-template-columns: 1fr 1fr; } }

/* ==========================================================================
   Trust / promise
   ========================================================================== */
.promise { text-align: center; max-width: 60rem; margin-inline: auto; }
.promise .eyebrow { justify-content: center; }
.promise-media {
  aspect-ratio: 21 / 9;
  margin: 0 0 clamp(2rem, 4vw, 2.75rem);
}
.promise blockquote {
  margin: 0 0 1.5rem;
  font-family: var(--font-serif);
  font-size: clamp(1.7rem, 4vw, 2.9rem);
  line-height: 1.18;
  color: #fff;
  text-wrap: balance;
}
.promise .support { color: #DAE2DB; font-size: 1.1rem; max-width: 60ch; margin: 0 auto 2.75rem; }
/* .testimonial / .cite removed 2026-08-02 with the placeholder markup on
   index.html — archived together in archive/home-testimonial-placeholder.html. */

/* ==========================================================================
   Bottom banner
   ========================================================================== */
.cta-banner { text-align: center; padding: clamp(4rem, 8vw, 7rem) 0; }
.cta-banner h2 { font-size: clamp(2rem, 4.5vw, 3.2rem); color: #fff; margin-bottom: 1rem; }
.cta-banner p { color: #DAE2DB; font-size: 1.15rem; max-width: 44ch; margin: 0 auto 2rem; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer { background: var(--forest-ink); color: #CFD9D1; padding: clamp(3.5rem, 6vw, 5rem) 0 2.5rem; }
.footer-top { display: grid; gap: 2.5rem; grid-template-columns: 1fr; margin-bottom: 3rem; }
.footer-brand { display: flex; flex-direction: column; gap: 1rem; max-width: 30ch; }
.footer-lockup { display: inline-flex; align-items: center; gap: .8rem; }
.footer-lockup img { height: 42px; width: auto; }
.footer-lockup .wm { font-family: var(--font-sans); font-weight: 800; text-transform: uppercase; letter-spacing: .01em; font-size: 1.15rem; color: #F4F1EA; }
.footer-brand .tag { font-family: var(--font-serif); font-style: italic; color: #A9BCB0; }
.footer-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; }
.footer-cols h3 { font-family: var(--font-sans); font-size: .72rem; text-transform: uppercase; letter-spacing: .14em; color: #86988C; font-weight: 700; margin-bottom: 1rem; }
.footer-cols ul { display: flex; flex-direction: column; gap: .7rem; }
.footer-cols a { text-decoration: none; color: #CFD9D1; font-size: .95rem; transition: color .2s var(--ease); }
.footer-cols a:hover { color: #fff; }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.1);
  padding-top: 1.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.5rem;
  justify-content: space-between;
  font-size: .82rem;
  color: #86988C;
}
/* Inherits the .82rem/#86988C floor already documented as passing (4.71:1)
   for this ground — the underline is a second cue so the link never relies on
   color alone to read as interactive. */
.footer-bottom a { color: inherit; text-decoration: underline; text-underline-offset: 2px; transition: color .2s var(--ease); }
.footer-bottom a:hover, .footer-bottom a:focus-visible { color: #fff; }
@media (min-width: 760px) {
  .footer-top { grid-template-columns: 1.4fr 1fr; }
  .footer-cols { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   Scroll reveal
   ========================================================================== */
/* Reveal is gated on html.has-reveal (added by JS only when supported + motion allowed),
   so no-JS / reduced-motion visitors always see fully-visible content. */
html.has-reveal .reveal { opacity: 0; transform: translateY(18px); }
html.has-reveal .reveal.in { opacity: 1; transform: none; transition: opacity .7s var(--ease), transform .7s var(--ease); }
@media (prefers-reduced-motion: reduce) {
  html.has-reveal .reveal { opacity: 1; transform: none; }
  /* Matches the .hero-bg rule: hold the mosaic still even if the script has
     already written a drift offset before the preference was applied. */
  .mosaic-grid .media { translate: none !important; will-change: auto; }
  .compare--versus .bar__fill { transform: none !important; transition: none; }
  .btn, .pillar, .arrow-link, .nav a::after { transition: none; }
}
