/* ==========================================================================
   Vertical Systems homepage: page styles
   --------------------------------------------------------------------------
   Load order: engine/scrollcraft.css (floor) > assets/themes.css (tokens,
   [data-theme="field"]) > this file > css/components.css (shared cards,
   buttons, chips, reveal; owned by the pages workflow, never edited here) >
   css/acts/NN-name.css (linked by scripts/build-home.mjs) >
   css/site-menu.css > css/footer.css. Colour and type come from the theme;
   this file owns the page frame: tokens the sections share, the logo, the
   bar, the legacy .btn buttons, the hero slot, shared hooks and the stub
   floor. The footer is in css/footer.css. Each section styles itself in
   css/acts/NN-name.css (site/sections/README.md).

   Shared hooks for sections:
     --vs-chrome-h       fixed chrome over the page (the bar). Pad pinned
                         stages with it.
     --vs-section-pad    vertical padding of a flow section
                         (docs/DESIGN-SYSTEM.md: clamp(3.5rem, 8vw, 6.5rem))
     --vs-h2             the section headline size; --vs-head-gap the space
                         under a section head
     --vs-mono           the palette's mono face
     --vs-paper ...      a second, lighter ground for printed-looking panels
     .vs-vh              visually hidden text
     .vs-release-tag     the "Release pending" tag the build adds to records
     html.vs-no-engine   the engine did not mount: reveals show settled
     [data-vs-stub]      a section still waiting for its agent (plain floor)

   The hero section (js/hero-mount.js owns the swap):
     #hero.hero-slot     the static, crawlable default (agent-field's copy).
                         What no-JS visitors and crawlers see.
     #hero.is-mounting   a rotating hero is being mounted into .hero-layer,
                         hidden and inert, laid over the static copy.
     #hero.hero-host     the mounted hero. The static copy is gone; the hero
                         module owns everything inside .hero-layer, including
                         its own sticky stage, so #hero is not a scrollcraft act.
     #hero-copy          the static copy block and its four children.
     .bar.is-scrolled    added by js/home.js once the page has scrolled a bar
                         height, or #hero's bottom edge passes under the bar,
                         whichever comes first. Any hero height works.
     --vs-bar-h          the bar height, read by the heroes for stage padding.

   Grounds: sections alternate --sc-canvas (bone) and --sc-surface (paper)
   with hard edges and a hairline, never a drift.
   ========================================================================== */

:root {
  --vs-bar-h: 4rem;
  --vs-chrome-h: var(--vs-bar-h);
  --vs-r: 6px;                       /* one radius for buttons and small parts */
  --vs-mono: var(--vs-font-mono, ui-monospace, monospace);
  --sc-font-mono: var(--vs-mono);    /* .sc-label uses the palette mono */
  --vs-section-pad: clamp(3.5rem, 8vw, 6.5rem);
  --vs-h2: clamp(1.9rem, 1.35rem + 2.1vw, 2.9rem);
  --vs-head-gap: clamp(1.75rem, 3.5vw, 2.75rem);
}

/* Paper tokens. Zero specificity, so a palette block in assets/themes.css
   that defines them wins. Paper ink 17:1, soft 7:1, accent on paper 4.9:1. */
:where(html) {
  --vs-paper: #FBFAF6;
  --vs-paper-ink: #161715;
  --vs-paper-ink-soft: #55584F;
  --vs-accent-paper: #B84E08;
}

html { background: var(--sc-canvas); }
body { min-height: 100svh; }

/* Shared hooks. */
.vs-vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.vs-release-tag {
  display: inline-block; vertical-align: 0.15em;
  margin-inline-start: 0.5em; padding: 0.15em 0.45em;
  font-family: var(--vs-mono); font-size: var(--sc-t-xs); font-weight: 400;
  letter-spacing: 0.02em; line-height: 1.2; text-transform: none;
  color: var(--sc-ink-soft);
  border: 1px solid var(--vs-line-strong); border-radius: 3px;
}
.vs-release-tag { color: var(--sc-ink); border-style: dashed; }

main > section[id] { scroll-margin-top: var(--vs-chrome-h); }

/* Flow sections take the design-system padding through the engine token, so
   a section that sets its own padding-block still wins by source order. */
main > .sc-section { --sc-section: var(--vs-section-pad); }
/* Less air under a section than above its heading: the gap belongs to the
   boundary (the hairline), and two full pads back to back read as an empty
   band (Mani's review, 16 Sep 2026). Pinned sections set their own. */
main > .sc-section:not(.sc-act--pinned) { padding-block-end: calc(var(--vs-section-pad) * 0.7); }

/* ------------------------------------------------------------ stub floor -- */
/* Sections 10, 20 and 30 ship as stubs until their agents replace them.
   Plain and readable, so the page never shows an empty band. */
[data-vs-stub] { border-top: 1px solid var(--vs-line); }
.vs-stub__title {
  margin: 0 0 var(--vs-head-gap);
  font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--vs-h2); line-height: var(--sc-leading-tight);
  letter-spacing: var(--vs-display-track); text-wrap: balance;
}
.vs-stub__list { display: flex; flex-wrap: wrap; gap: var(--sc-2) var(--sc-5); margin: 0; padding: 0; list-style: none; }
.vs-stub__link { color: var(--sc-ink); font-weight: 500; text-underline-offset: 0.3em; }
.vs-stub__grid {
  display: grid; gap: var(--sc-4); margin: 0; padding: 0; list-style: none;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.vs-stub__claim {
  margin: 0; font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--sc-t-xl); letter-spacing: var(--vs-display-track); line-height: 1.1;
}
.vs-stub__chip { margin: var(--sc-3) 0 0; }

/* The engine hides flow reveals until it mounts. If it never does, show them. */
html.vs-no-engine [data-sc-in],
html.vs-no-engine [data-sc-stagger] > * { opacity: 1; transform: none; }

/* The grain is written for dark grounds at 4.5%. On bone it is paper tooth,
   and it wants less. */
.sc-grain { opacity: 0.03; }

/* ------------------------------------------------------------- skip link -- */
.skip {
  position: fixed; top: var(--sc-3); left: var(--sc-3); z-index: 100;
  padding: var(--sc-2) var(--sc-4);
  background: var(--sc-ink); color: var(--sc-canvas);
  font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--sc-t-sm); text-decoration: none; border-radius: var(--vs-r);
  transform: translateY(-160%);
}
.skip:focus-visible { transform: none; outline-color: var(--sc-accent); }

/* ------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 2.75rem; padding: 0 1.125rem;
  font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--sc-t-sm); letter-spacing: -0.005em; line-height: 1;
  white-space: nowrap; text-decoration: none;
  border-radius: var(--vs-r); border: 1px solid transparent;
  transition: background-color var(--sc-d-fast) var(--sc-ease-out),
              border-color var(--sc-d-fast) var(--sc-ease-out),
              transform 100ms var(--sc-ease-out);
}
.btn:active { transform: translateY(1px); }
.btn--primary {
  background: var(--sc-accent); color: var(--sc-accent-ink);
  border-color: color-mix(in oklab, var(--sc-accent) 80%, var(--sc-ink));
}
.btn--primary:hover { background: color-mix(in oklab, var(--sc-accent) 88%, var(--sc-ink)); }
.btn--primary:focus-visible { outline-color: var(--sc-ink); }
.btn--ghost {
  background: transparent; color: var(--sc-ink);
  border-color: var(--vs-line-strong);
}
.btn--ghost:hover { background: var(--sc-surface); border-color: var(--sc-ink); }

/* ---------------------------------------------------------------- logo -- */
/* The approval V (docs/brand/vs-mark.svg) and the VERTICAL SYSTEMS wordmark,
   used by the bar, the menu (css/site-menu.css places it) and the footer
   (css/footer.css sizes it). The mark's SVG has no ids, so it repeats
   safely. The wordmark face is Archivo at width 125 and weight 700, loaded as
   a small subset in each page's head; until it arrives, the theme's display
   face stands in.
     --logo-mark        the mark's height; the wordmark scales from it
     .vs-logo--stack-sm the wordmark on two lines at phone widths, so the bar
                        keeps room for its two buttons */
.vs-logo {
  --logo-mark: 1.625rem;
  display: inline-flex; align-items: center; gap: calc(var(--logo-mark) * 0.4);
  color: var(--sc-ink); text-decoration: none; white-space: nowrap;
}
.vs-mark {
  display: block; flex: none; overflow: visible;
  height: var(--logo-mark); width: calc(var(--logo-mark) * 104 / 87);
}
.vs-mark__v { fill: currentColor; }
.vs-mark__ring {
  fill: none; stroke: var(--foot-ok, var(--vs-ok)); stroke-width: 4;
  transform-box: fill-box; transform-origin: center;
  transition: transform 260ms var(--sc-ease-out);
}
.vs-mark__dot {
  fill: var(--sc-accent);
  transform-box: fill-box; transform-origin: center;
  transition: fill 200ms var(--sc-ease-out), transform 260ms var(--sc-ease-out);
}
.vs-logo__word {
  font-family: "Archivo", var(--sc-font-display);
  font-stretch: 125%; font-weight: 700;
  font-size: calc(var(--logo-mark) * 0.56); line-height: 1;
  letter-spacing: 0.02em; text-transform: uppercase;
}
.vs-logo:focus-visible { outline-offset: 5px; }
@media (hover: hover) {
  .vs-logo:hover .vs-mark__ring { transform: scale(1.16); }
  .vs-logo:hover .vs-mark__dot {
    fill: color-mix(in oklab, var(--sc-accent) 80%, var(--sc-canvas));
    transform: scale(1.08);
  }
}
@media (max-width: 520px) {
  .vs-logo--stack-sm { --logo-mark: 1.5rem; gap: 0.5rem; }
  .vs-logo--stack-sm .vs-logo__word { font-size: 0.6875rem; line-height: 1.08; letter-spacing: 0.03em; }
  .vs-logo--stack-sm .vs-logo__word > span { display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .vs-mark__ring, .vs-mark__dot { transition: none; }
  .vs-logo:hover .vs-mark__ring, .vs-logo:hover .vs-mark__dot { transform: none; }
}
@media (forced-colors: active) {
  .vs-mark__ring { stroke: CanvasText; }
  .vs-mark__dot { fill: Highlight; }
}

/* ----------------------------------------------------------------- bar -- */
.bar {
  position: fixed; inset: 0 0 auto 0; z-index: var(--sc-z-chrome);
  height: var(--vs-bar-h);
  background: transparent;
  box-shadow: 0 1px 0 transparent;
  transition: background-color 200ms var(--sc-ease-out),
              box-shadow 200ms var(--sc-ease-out);
}
.bar.is-scrolled {
  background: color-mix(in oklab, var(--sc-canvas) 94%, transparent);
  box-shadow: 0 1px 0 var(--vs-line);
}
.bar__inner {
  height: 100%; max-width: var(--sc-maxw); margin-inline: auto;
  padding-inline: var(--sc-gutter);
  display: flex; align-items: center; gap: var(--sc-6);
}
.bar__brand { flex: none; }
.bar__nav { display: flex; gap: var(--sc-5); margin-inline-start: var(--sc-2); }
.bar__nav a {
  color: var(--sc-ink); text-decoration: none; font-size: var(--sc-t-sm);
  font-weight: 500; padding-block: var(--sc-2);
  text-underline-offset: 0.3em; text-decoration-thickness: 1px;
}
.bar__nav a:hover { text-decoration: underline; }
.bar__actions { margin-inline-start: auto; display: flex; align-items: center; gap: var(--sc-3); }
.bar__cta-short { display: none; }
.bar__menu {
  display: none; height: 2.75rem; padding: 0 0.875rem;
  background: transparent; border: 1px solid var(--vs-line-strong);
  border-radius: var(--vs-r); color: var(--sc-ink);
  font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--sc-t-sm); cursor: pointer;
}
.bar__menu:hover { background: var(--sc-surface); }
.bar__menu:active { transform: translateY(1px); }

/* ------------------------------------------------------------ hero slot -- */
.hero-slot {
  min-height: 100svh;
  display: grid; align-items: center;
  padding: calc(var(--vs-bar-h) + var(--sc-8)) var(--sc-gutter) var(--sc-9);
  background: var(--sc-canvas);
}
.hero-slot__copy {
  width: 100%; max-width: var(--sc-maxw); margin-inline: auto;
}
.hero-slot__title {
  margin: 0; max-width: 12ch;
  font-family: var(--sc-font-display); font-weight: var(--vs-display-weight);
  font-size: var(--sc-t-4xl); line-height: 0.96;
  letter-spacing: var(--vs-display-track); text-wrap: balance;
}
.hero-slot__sub {
  margin: var(--sc-5) 0 0; max-width: 40ch;
  font-size: var(--sc-t-lg); line-height: 1.42; letter-spacing: var(--sc-track-snug);
  color: var(--sc-ink-soft); text-wrap: pretty;
}
.hero-slot__cta { display: flex; flex-wrap: wrap; gap: var(--sc-3); margin-top: var(--sc-6); }
.hero-slot__free { margin: var(--sc-5) 0 0; font-size: var(--sc-t-sm); color: var(--sc-ink-soft); }
.hero-slot__free a { color: inherit; text-underline-offset: 0.3em; }
.hero-slot__free a:hover { color: var(--sc-ink); }

/* The mount layer: laid out for real (heroes measure themselves on mount)
   but invisible and out of the way until the swap. */
.hero-slot.is-mounting { position: relative; }
.hero-slot > .hero-layer {
  position: absolute; inset: 0 0 auto 0;
  visibility: hidden; opacity: 0; pointer-events: none;
}
/* Never shorter than the static default it replaced, so nothing below it
   moves up. Every hero is taller than this. */
.hero-host { position: relative; min-height: 100svh; background: var(--sc-canvas); }
.hero-host > .hero-layer { animation: hero-layer-in 240ms var(--sc-ease-out) backwards; }
@keyframes hero-layer-in { from { opacity: 0; } to { opacity: 1; } }

/* -------------------------------------------------------------- anchors -- */
.anchor { display: block; height: 0; scroll-margin-top: calc(var(--vs-chrome-h) + var(--sc-4)); }

/* --------------------------------------------------------------- phones -- */
@media (max-width: 860px) {
  :root { --vs-bar-h: 3.5rem; }
  .bar__inner { gap: var(--sc-3); }
  .bar__nav { display: none; }
  .bar__menu { display: inline-flex; align-items: center; }
  .bar__cta-long { display: none; }
  .bar__cta-short { display: inline; }
  .bar__cta { height: 2.5rem; padding: 0 0.875rem; }
  .bar__menu { height: 2.5rem; }

  .hero-slot { padding-top: calc(var(--vs-bar-h) + var(--sc-7)); padding-bottom: var(--sc-8); }
  .hero-slot__cta .btn { flex: 1 1 100%; }
}
@media (max-width: 700px) {
  .hero-slot__title { font-size: var(--sc-t-3xl); max-width: none; }
}
@media (max-width: 400px) {
  .bar__cta { padding: 0 0.75rem; }
}

/* ------------------------------------------------------- reduced motion -- */
@media (prefers-reduced-motion: reduce) {
  .hero-host > .hero-layer { animation: none; }
  .btn, .bar, .skip { transition: none; }
}
