/* ==========================================================================
   VaultedOS — Base + shared primitives
   Every section MUST build from these. Do not redefine buttons, eyebrows,
   headings, or containers inside a section file.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-weight: var(--fw-medium);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--bg-deep);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
/* `list-style: none` makes Safari/VoiceOver drop list semantics entirely, so
   every unstyled list on the site stops announcing as a list. An EMPTY
   list-style-type removes the marker while keeping the semantics, which is why
   it is preferred over `none` — and it means sections don't each have to
   remember `role="list"`. `none` stays as the fallback for older engines. */
ul, ol { margin: 0; padding: 0; list-style: none; }
@supports (list-style-type: "") {
  ul, ol { list-style-type: ""; }
}
h1, h2, h3, h4, p { margin: 0; }

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

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

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */

.vos-section {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(56px, 7vw, 104px);
  /* The nav is position:fixed, so an in-page anchor lands UNDER it — measured
     at 75px (375) to 90px (1440) of the target hidden. The first two terms are
     the nav's exact geometry (its top offset + its 65px height) so this tracks
     automatically if the nav is ever resized; +16px is breathing room. */
  scroll-margin-top: calc(clamp(10px, 1.74vw, 25px) + 65px + 16px);
}

/* --container is the CONTENT width (1232 = Figma's 1440 frame less its 104px
   margins). The gutter is added OUTSIDE it, so content actually measures 1232
   at wide viewports. Putting the padding inside the max-width — the original
   bug — silently squeezed every section to ~1088. */
.vos-container {
  width: 100%;
  max-width: calc(var(--container) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Centered heading stack used by most sections. */
.vos-head { text-align: center; max-width: 720px; margin-inline: auto; }
.vos-head--left { text-align: left; margin-inline: 0; }

/* --------------------------------------------------------------------------
   Bands — dark is default; add .vos-section--light for the pastel bands.
   -------------------------------------------------------------------------- */

.vos-section--alt { background: var(--bg-deep-2); }

.vos-section--light {
  background: var(--lt-bg-wash);
  color: var(--lt-text);
}
/* --vos-blue is only 2.7:1 on white and fails AA as text. Light bands get the
   darker ink blue instead — same hue, readable. */
.vos-section--light .vos-eyebrow { color: var(--vos-blue-ink); }
.vos-section--light .vos-h2 { color: var(--lt-text); }
.vos-section--light .vos-sub,
.vos-section--light .vos-body { color: var(--lt-text-muted); }

/* Hairline divider that reads as light catching an edge. */
.vos-hairline {
  height: 1px; width: 100%; border: 0; margin: 0;
  background: var(--vos-grad-hairline);
}

/* --------------------------------------------------------------------------
   Typography primitives
   -------------------------------------------------------------------------- */

/* Eyebrow: uppercase, 18px. Figma uses SOLID blue in most frames and the
   blue→mint gradient only in the hero — so solid is the default and the
   gradient is the opt-in variant, not the other way round. */
.vos-eyebrow {
  display: inline-block;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--vos-blue);
}

.vos-eyebrow--grad {
  background: var(--vos-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Mint "status" pill — the sentence-case label above each product-feature
   heading (statements / receipts / reports). All three built this by hand
   independently, so it lives here now to stop the three drifting apart. */
.vos-pill--mint {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  height: 20px;
  padding: 0 var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: 1;
  color: var(--vos-mint-bright);
  background: rgba(95, 252, 192, .10);
  border: 0;
}
.vos-pill--mint::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--vos-mint-bright);
  box-shadow: 0 0 8px var(--vos-mint-bright);
}
/* #5ffcc0 on white is ~1.3:1 — light bands need the dark-green ink. */
.vos-section--light .vos-pill--mint {
  color: #0a7355;
  background: rgba(10, 115, 85, .08);
  border-color: rgba(10, 115, 85, .22);
}
/* The dot was left on the bright mint and read as a pale smudge on white. */
.vos-section--light .vos-pill--mint::before {
  background: #0a7355;
  box-shadow: none;
}

/* Eyebrow wrapped in the translucent glass pill (hero + comparison). */
.vos-eyebrow-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  height: 33px;
  padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--vos-grad-soft);
  backdrop-filter: blur(6.55px);
  -webkit-backdrop-filter: blur(6.55px);
}

.vos-display {
  font-size: var(--fs-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
}

.vos-h1 {
  font-size: var(--fs-h1);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
}

.vos-h2 {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  color: var(--text);
}

/* Feature-row heading — the 32px level inside statements/receipts/reports. */
.vos-feature-h {
  font-size: var(--fs-feature);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
}

/* 20px section sub-copy that sits under a .vos-h2. Weight is reset to 400
   because body is 500 — Figma's sub-copy is Regular, and inheriting made
   every section using this render one weight heavy. */
.vos-lead {
  font-size: var(--fs-lead);
  font-weight: var(--fw-regular);
  color: var(--text-muted);
  line-height: var(--lh-lead);
}

/* 24px card title — the level between --fs-h3 (20) and --fs-feature (32). */
.vos-title {
  font-size: var(--fs-title);
  font-weight: var(--fw-semibold);
  line-height: 1.3;
}
.vos-section--light .vos-lead { color: var(--lt-text-muted); }

.vos-h3 {
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  line-height: 1.3;
}

/* Body-copy primitives reset weight to 400. Body is Medium (500) for UI, but
   Figma sets prose Regular — inheriting rendered all sub-copy a weight heavy. */
.vos-sub {
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  color: var(--text-muted);
  line-height: var(--lh-body);
}

.vos-body {
  font-weight: var(--fw-regular);
  color: var(--text-muted);
}

.vos-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-dim);
}

/* The gradient word treatment — "write it!"
   Two sections independently hit the same footgun: overriding the gradient with
   the `background` SHORTHAND silently resets background-clip to border-box, so
   the text renders as a solid coloured bar instead of clipped type. Declared
   with background-IMAGE, and the clip is !important so a shorthand override
   can't defeat it. If you are re-colouring this, set `background-image`. */
.vos-grad-text {
  background-image: var(--vos-grad);
  -webkit-background-clip: text !important;
  background-clip: text !important;
  color: transparent;
}

/* --------------------------------------------------------------------------
   Buttons — exact Figma geometry: 44px tall, 12px radius, 24px inline pad.
   -------------------------------------------------------------------------- */

.vos-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--h-control);
  padding: var(--sp-2) var(--sp-6);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-ui);
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.vos-btn:hover { transform: translateY(-1px); }
/* A real pressed state, not just "cancel the hover lift" — the button sinks
   below its resting position and dims, so a press reads on every variant. */
.vos-btn:active {
  transform: translateY(1px) scale(.985);
  filter: brightness(.92);
  transition-duration: 60ms;
}

/* Primary: transparent fill, blue hairline border, soft outer bloom. */
.vos-btn--primary {
  color: #fff;
  border-color: var(--vos-blue);
  background: rgba(80, 161, 249, .06);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  box-shadow: 0 0 18px rgba(80, 161, 249, .30),
              inset 0 1px 0 rgba(255, 255, 255, .06);
}
.vos-btn--primary:hover {
  background: rgba(80, 161, 249, .14);
  box-shadow: 0 0 26px rgba(80, 161, 249, .48),
              inset 0 1px 0 rgba(255, 255, 255, .10);
}

/* Secondary: dark glass with a subtle catch of fine gold guilloche wave
   lines — the SAME wave plate the hero background uses, so the two read as
   one material at different crops. This is a transcription of Figma
   4293:100, which is NOT a glow and NOT a fully-patterned gold surface: the
   "try2 2" wave plate is an alpha mask over a #ffc300 fill (children
   4293:105–107), then a rgba(0,0,0,.3) scrim (4293:108) darkens the WHOLE
   pill — lines and glass alike — on a rgba(255,255,255,.05) glass base.
   A radial-gradient stood in for it here once and rendered as a hard-edged
   yellow strip; a scrimless wave at .72 stood in for it next and rendered
   markedly bolder than the file — a gold-patterned button instead of dark
   glass. The scrim is now literal: ::before is the full-strength gold wave
   (mask asset assets/img/hero/btn-gold-wave.webp, the plate's top slice
   pre-flipped as Figma flips it, anchored top-left as Figma anchors it;
   alpha = the lines, fill = the --vos-gold token) and ::after is the .3
   black scrim above it. Hover thins the scrim ("the light catches")
   instead of repainting anything.
   Still no `overflow: hidden`: both pseudos clip on their own border-radius,
   so a long label can never be hidden by the button, and the :focus-visible
   outline (drawn outside the box) is never swallowed. */
.vos-btn--gold {
  /* isolation traps the negative-z wave + scrim between this button's own
     background and its label, instead of letting them escape under ancestor
     backgrounds. Paint order inside: glass bg, wave (-2), scrim (-1), label. */
  isolation: isolate;
  color: #fff;
  background: rgba(255, 255, 255, .05);
  box-shadow: var(--shadow-btn);
  text-shadow: 0 2px 8.6px rgba(0, 0, 0, .9);
}
.vos-btn--gold::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -2;
  background: var(--vos-gold);
  -webkit-mask-image: url('../assets/img/hero/btn-gold-wave.webp');
  mask-image: url('../assets/img/hero/btn-gold-wave.webp');
  -webkit-mask-size: cover;
  mask-size: cover;
  -webkit-mask-position: top left;
  mask-position: top left;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.vos-btn--gold::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: -1;
  background: rgba(0, 0, 0, .3);
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.vos-btn--gold:hover::after { opacity: .35; }
.vos-btn--gold:hover { box-shadow: var(--shadow-btn), 0 0 16px rgba(255, 195, 0, .16); }

/* Ghost: for light bands and tertiary actions. */
.vos-btn--ghost {
  color: var(--text);
  border-color: var(--stroke-strong);
  background: var(--bg-panel);
}
.vos-btn--ghost:hover { border-color: var(--vos-blue); background: var(--bg-panel-2); }

.vos-section--light .vos-btn--ghost {
  color: var(--lt-text);
  border-color: var(--lt-stroke);
  background: #fff;
}

/* --------------------------------------------------------------------------
   Surfaces — glass card, per the "glass edge" house style.
   -------------------------------------------------------------------------- */

.vos-card {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--stroke);
  background: var(--bg-panel);
  backdrop-filter: blur(var(--blur-glass));
  -webkit-backdrop-filter: blur(var(--blur-glass));
  box-shadow: var(--shadow-card);
}

/* Sharp light-catch on the upper-left / lower-right edges. */
.vos-card--edge::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg,
              rgba(255,255,255,.30) 0%,
              rgba(255,255,255,.02) 32%,
              rgba(255,255,255,.02) 68%,
              rgba(139,227,202,.24) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.vos-section--light .vos-card {
  border-color: var(--lt-stroke);
  background: var(--lt-panel);
  box-shadow: var(--shadow-card-lt);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* --------------------------------------------------------------------------
   Ambient background helpers (the radial glows behind dark sections)
   -------------------------------------------------------------------------- */

.vos-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  z-index: -1;
  opacity: .5;
}
.vos-glow--blue { background: radial-gradient(circle, rgba(80,161,249,.55), transparent 68%); }
.vos-glow--mint { background: radial-gradient(circle, rgba(139,227,202,.40), transparent 68%); }

/* `.vos-engrave` was REMOVED. It painted a guilloche wave texture behind the
   dark bands, but a Figma audit found neither frame that used it (testimonials
   4309:2, why-vaulted 4010:473) has ANY texture layer — it was a house
   invention, and the owner asked to match the file. Do not reintroduce it.
   The wave asset it referenced is still live: the dashboard's own plate, which
   IS in Figma, uses assets/img/shared/guilloche-wave.webp. */

/* --------------------------------------------------------------------------
   Scroll reveal — opt in with .vos-reveal; script.js adds .is-in.
   -------------------------------------------------------------------------- */

/* Progressive enhancement: the hidden start state is applied ONLY when the
   `js` class is present (set by an inline script in <head>). Without it the
   content renders normally. Previously a JS failure — or an observer that
   never fired — left whole sections permanently invisible. */
.js .vos-reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
.js .vos-reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .vos-reveal { opacity: 1; transform: none; transition: none; }
}

/* --------------------------------------------------------------------------
   Scan list — prose that wants to be read in one pass
   --------------------------------------------------------------------------
   Body copy on this site kept growing into four-line paragraphs that say three
   things. A visitor scans a marketing page; they do not read it. This is the
   shape for "here are the three things", and it should be reached for whenever
   a paragraph contains a list wearing sentence clothing.

   The marker is a rule, not a disc: a dot competes with the product shots'
   own status dots, which carry state and must stay the loudest small round
   thing on the page. Set `--vos-scan-mark` to re-colour it per band. */
.vos-scan {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: var(--sp-5) 0 0;
  padding: 0;
  list-style: none;
  max-width: 52ch;
}
.vos-scan li {
  position: relative;
  padding-left: var(--sp-6);
  line-height: 1.45;
}
.vos-scan li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .62em;
  width: 14px;
  height: 2px;
  border-radius: 2px;
  background: var(--vos-scan-mark, var(--vos-blue));
}
.vos-section--light .vos-scan li::before { background: var(--vos-scan-mark, var(--vos-blue-ink)); }
