/* The stylesheet for every rendered public page. Served at /assets/page.css.
 *
 * GENERATED, AND NOT FROM A FILE. There is no stylesheet in the source tree to edit. This text is
 * composed on request: the color roles, the corner-radius ramp, the de-emphasis opacity and the
 * spacing ramp are read from the published design artifacts and written out below, and the rules
 * that consume them are carried in the composition. What you are reading is that composition's
 * output, so an edit to these bytes has nowhere to persist.
 *
 * WHY AN EXTERNAL STYLESHEET AND NOT AN INLINE <style>
 *
 * An inline block would force `style-src 'unsafe-inline'` on these pages' Content-Security-Policy —
 * and `'unsafe-inline'` in `style-src` also permits `style-src-attr` by fallback, so an injected
 * `style="..."` attribute would take effect. CSS-only injection is not harmless: it can overlay or
 * reposition content, and exfiltrate through attribute selectors plus `url()`. A separate stylesheet
 * lets these pages run under `style-src 'self'`.
 *
 * That is only sound because the page serializer emits CLASS TOKENS ONLY: it admits style values from
 * closed allowlists and DROPS anything unrecognized rather than falling back to an inline style. So
 * every selector below is one the serializer can actually emit, and a style value with no rule here
 * renders unstyled rather than inline.
 *
 * THE ONLY ABSOLUTE COLORS are in the print block at the end, where black-on-white is the point.
 * Every other treatment reads a token, because a treatment written as a literal is one no contrast
 * gate can see — and at least one of them (white text on the accent fill, which is right in one
 * scheme only) was a real contrast failure that survived for exactly that reason.
 */

/* The token block is written in below (light here, dark further down) by the emitter every
   shell paints from — see the header. `color-scheme` tells the browser to theme its own form controls
   and scrollbars to match, which is what keeps a dark-mode page from flashing a white scrollbar. */
:root {
  color-scheme: light dark;
  /* Reserve the scrollbar's gutter whether or not this page scrolls. The frame is centred, so on a
     platform with classic (space-taking) scrollbars a short page — /pricing, /delete-account, a 404 —
     is laid out ~15px wider than a long help article, and the centred content shifts sideways on
     navigation for a reason that has nothing to do with the layout. Inert where scrollbars overlay. */
  scrollbar-gutter: stable;
  --fv-accent: #007C59;
  --fv-accent-hover: #006A4B;
  --fv-accent-pressed: #00593E;
  --fv-accent-subtle: rgba(0,124,89,0.1);
  --fv-bg-base: #FDFCFC;
  --fv-bg-elevated: #FFFFFF;
  --fv-bg-hover: #F0EEEB;
  --fv-bg-primary: #FFFFFF;
  --fv-bg-secondary: #FAF9F8;
  --fv-bg-tertiary: #F5F3F1;
  --fv-border: #DCD8D3;
  --fv-border-focus: #007C59;
  --fv-border-subtle: #E5E2DD;
  --fv-highlight: #DF6C40;
  --fv-highlight-subtle: rgba(223,108,64,0.1);
  --fv-overlay: rgba(0,0,0,0.5);
  --fv-error: #D24D45;
  --fv-error-subtle: rgba(210,77,69,0.1);
  --fv-error-text: #B7423B;
  --fv-info: #2784D5;
  --fv-info-subtle: rgba(39,132,213,0.1);
  --fv-info-text: #2172B9;
  --fv-success: #2E9E52;
  --fv-success-subtle: rgba(46,158,82,0.1);
  --fv-success-text: #1F8441;
  --fv-warning: #D98B09;
  --fv-warning-subtle: rgba(217,139,9,0.1);
  --fv-warning-text: #996000;
  --fv-text-inverse: #FFFFFF;
  --fv-text-muted: #76716A;
  --fv-text-primary: #34312E;
  --fv-text-secondary: #726E68;
  --fv-font-logo: Bebas Neue, Industry, sans-serif;
  --fv-font-mono: 'SF Mono', 'Fira Code', Consolas, monospace;
  --fv-font-sans: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --fv-radius-2xl: 28px;
  --fv-radius-full: 9999px;
  --fv-radius-lg: 14px;
  --fv-radius-md: 10px;
  --fv-radius-none: 0;
  --fv-radius-sm: 6px;
  --fv-radius-xl: 20px;
  --fv-shadow-inner: inset 0 2px 4px rgba(28,25,23,0.06);
  --fv-shadow-lg: 0 12px 24px rgba(28,25,23,0.12);
  --fv-shadow-md: 0 4px 12px rgba(28,25,23,0.08);
  --fv-shadow-sm: 0 1px 2px rgba(28,25,23,0.05);
  --fv-shadow-xl: 0 24px 48px rgba(28,25,23,0.16);
  --fv-disabled: 0.5;
  --fv-muted: 0.6;
  /* The type faces above are the design system's own, and the first of them IS webfont-loaded —
     but NOT FROM THIS FILE. The document head links `/vendor/inter.css`, the same vendored sheet the
     app shell links, and preloads the latin subset; the page policy carries `font-src 'self'` to admit
     it. Two properties are worth keeping straight, because a reader who finds a font stack and no
     `@font-face` will otherwise conclude one of them is broken:

       * THE FACES MUST NOT BE DECLARED HERE. The subset table (which file, which `unicode-range`) is a
         mapping, and a mapping implemented twice drifts silently — the defect the shared token emitter
         exists to prevent, one layer down. It lives beside the bytes it describes and is regenerated
         with them, so this stylesheet names no font URL at all and a test holds it to that.
       * THIS IS NOT A BLOCKING FONT REQUEST, which is what an earlier note here weighed it as and
         rejected. The face sheet is discovered in the same head parse as this one and fetched
         concurrently, the preload warms the one face an English page needs, and `font-display: swap`
         paints text in the fallback immediately either way. What a reader can still see is a swap
         reflow, not a delayed first paint — and the surface it buys is the FIRST one a customer meets,
         which until now rendered the product's own typeface only for readers who happened to have it
         installed locally.

     TWO widths follow, and the distinction between them IS the layout system. They are the page's
     OWN tokens — not the emitter's — because a frame width is a property of this document shape and
     of nothing a shell renders.

     `--fv-frame` is the page FRAME: the width of `<main>` AND of the header and footer bands' inner
     wrappers, and so the left gutter every page shares. It is deliberately the SAME value on every
     layout. It used to be per-layout (60rem landing/index, 52rem marketing, 46rem document), and
     because the header and footer then lived INSIDE `<main>`, the wordmark, the nav links, and the
     footer columns all moved horizontally on every navigation — 60 → 52 → 60 → 46rem walking the
     landing page to pricing to the help index to a help article. A frame that shifts between two
     pages of one site reads as a rendering fault rather than as a layout, so no layout may set it.
     The bands are now outside `<main>`, so the failure is quieter and worse: only the article would
     slide, pulling its left edge out of line with the wordmark right above it.

     `--fv-measure` is the reading COLUMN: the line length running text is held to, inside that frame.
     Layouts differ in WHAT they hold to it — a document holds its whole article, a landing page holds
     only its prose and lets its composed blocks span the frame — never in how wide the frame is. */
  --fv-frame: 60rem;
  --fv-measure: 46rem;
}

/* `screen and`, on this block and on the three other dark arms in this file: the dark palette is a
   SCREEN palette, and print is the medium where saying so matters. The print block at the end of this
   file sets black-on-white for `body`, but everything that reads a token instead — secondary text,
   borders, a code block's fill — would print from whichever palette the query resolved. So on a
   browser that evaluates `prefers-color-scheme: dark` while printing, a legal document came out with
   #B8B3AE secondary text on white paper: legible on a screen, near-invisible on a sheet. Worse in the
   engine that also declines to print background colors by default, which removes the dark fill that
   made the light text readable but not the light text.

   Chrome and Safari force the light scheme for print, so this is belt-and-braces for them — but the
   behavior is a UA choice, not a guarantee this stylesheet can lean on, and the intent ("dark is for
   screens") is worth stating in the query rather than depending on. */
@media screen and (prefers-color-scheme: dark) {
  :root {
    --fv-accent: #2AC592;
    --fv-accent-hover: #47D9A5;
    --fv-accent-pressed: #00A074;
    --fv-accent-subtle: rgba(42,197,146,0.15);
    --fv-bg-base: #121110;
    --fv-bg-elevated: #242321;
    --fv-bg-hover: #2D2B28;
    --fv-bg-primary: #1A1918;
    --fv-bg-secondary: #1A1918;
    --fv-bg-tertiary: #242321;
    --fv-border: #514E49;
    --fv-border-focus: #2AC592;
    --fv-border-subtle: #423F3B;
    --fv-highlight: #FF8E63;
    --fv-highlight-subtle: rgba(255,142,99,0.15);
    --fv-overlay: rgba(0,0,0,0.5);
    --fv-error: #FD7468;
    --fv-error-subtle: rgba(253,116,104,0.15);
    --fv-error-text: #FD9186;
    --fv-info: #52A9FE;
    --fv-info-subtle: rgba(82,169,254,0.15);
    --fv-info-text: #78BAFC;
    --fv-success: #5AC576;
    --fv-success-subtle: rgba(90,197,118,0.15);
    --fv-success-text: #7BC98C;
    --fv-warning: #FAAB3F;
    --fv-warning-subtle: rgba(250,171,63,0.15);
    --fv-warning-text: #E4A65C;
    --fv-text-inverse: #121110;
    --fv-text-muted: #9D9790;
    --fv-text-primary: #EBE9E6;
    --fv-text-secondary: #B8B3AE;
    --fv-font-logo: Bebas Neue, Industry, sans-serif;
    --fv-font-mono: 'SF Mono', 'Fira Code', Consolas, monospace;
    --fv-font-sans: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --fv-radius-2xl: 28px;
    --fv-radius-full: 9999px;
    --fv-radius-lg: 14px;
    --fv-radius-md: 10px;
    --fv-radius-none: 0;
    --fv-radius-sm: 6px;
    --fv-radius-xl: 20px;
    --fv-shadow-inner: inset 0 2px 4px rgba(0,0,0,0.2);
    --fv-shadow-lg: 0 12px 24px rgba(0,0,0,0.5);
    --fv-shadow-md: 0 4px 12px rgba(0,0,0,0.4);
    --fv-shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
    --fv-shadow-xl: 0 24px 48px rgba(0,0,0,0.6);
    --fv-disabled: 0.5;
    --fv-muted: 0.6;
  }
}

/* ---- Document frame ---------------------------------------------------------------------- */

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

/* A column, so the footer can be pushed to the bottom of a short page. `min-height: 100svh` and not
   `100vh`: on mobile Safari `vh` is the tallest viewport (toolbar hidden), so `100vh` on a short page
   puts the footer just below the fold and the page scrolls a little for no content. `svh` is the
   SMALLEST viewport, which is the one that is always visible. `vh` stays as the fallback for a
   browser that does not know the unit. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--fv-bg-base);
  color: var(--fv-text-primary);
  font-family: var(--fv-font-sans);
  font-size: 1rem;
  line-height: 1.625;
  /* Both properties: the standard one, and the WebKit-prefixed spelling Safari still needs. Without
     it iOS Safari inflates text in landscape, which reflows the pricing table mid-scroll. */
  text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

/* The composition root — the single element between `<body>` and the three landmarks.
 *
 * It exists in the node tree so both composers (the lambda and `chrome.rs`) return ONE node, and it
 * used to carry no rule at all. It needs one now: the bottom-anchored footer is a two-link flex chain,
 * `body → page-root → .fv-page`, and a chain with a link missing collapses to content height, which
 * puts the footer of a one-line 404 floating in the middle of the window.
 *
 * `min-width: 0` comes from `.fv-container`; the width is NOT set here — a frame on this element would
 * be a second place that sizes the page, and it would un-band the header and footer by constraining
 * them before their own inner wrappers get the chance. */
.fv-role-page-root {
  flex: 1;
}

/* `<main class="fv-page">` — the article's frame, and the width the whole site shares.

   `flex: 1` is what makes the footer sit at the bottom of a short page rather than partway up it: the
   main region takes the slack in the body column. A one-line 404 with the footer floating mid-screen
   is the single clearest "this is an unstyled document" tell.

   ONE width for every layout (`--fv-frame`, see its note). The header and footer bands are held to
   the SAME token on their inner wrappers, so a per-layout `max-width` here would slide the article
   out of line with the wordmark directly above it. A layout narrows its own CONTENT (the `fv-layout-*`
   rules at the foot of this file); it never narrows the frame. */
.fv-page {
  flex: 1;
  width: 100%;
  max-width: var(--fv-frame);
  margin: 0 auto;
  padding: 32px 20px 96px;
}

/* ---- Layout primitives (§10 container props) --------------------------------------------- */

/* `min-width: 0` is load-bearing, not defensive tidying. A flex item's default `min-width: auto`
   refuses to shrink below its content's intrinsic width, so one long unbroken token (a URL in a
   legal document, a support address) widens its row past the viewport and the whole page scrolls
   sideways on a phone. */
.fv-container,
.fv-col,
.fv-row,
.fv-grid,
.fv-stack {
  min-width: 0;
}

.fv-container,
.fv-col,
.fv-row {
  display: flex;
}

.fv-col {
  flex-direction: column;
}

.fv-row {
  flex-direction: row;
  align-items: center;
}

.fv-wrap {
  flex-wrap: wrap;
}

/* `stack` overlays its children — a hero with a background layer behind its text. A single-cell
   grid rather than absolute positioning, so the stack still sizes to its tallest child instead of
   collapsing to zero height. */
.fv-stack {
  display: grid;
  grid-template-areas: "fv-stack";
}

.fv-stack > * {
  grid-area: fv-stack;
}

.fv-grid {
  display: grid;
  grid-template-columns: repeat(var(--fv-cols, 1), minmax(0, 1fr));
}

.fv-cols-1 { --fv-cols: 1 }
.fv-cols-2 { --fv-cols: 2 }
.fv-cols-3 { --fv-cols: 3 }
.fv-cols-4 { --fv-cols: 4 }
.fv-cols-5 { --fv-cols: 5 }
.fv-cols-6 { --fv-cols: 6 }

/* Below the phone breakpoint every multi-column grid collapses to one column. A 3-up plan grid at
   360px gives each card ~100px, which truncates the price. Single-column is the only honest answer
   and it is why the plans grid needs no per-page media query. */
@media (max-width: 40rem) {
  .fv-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.fv-inline {
  display: inline-flex;
  align-items: baseline;
}

/* align (cross axis) / justify (main axis) — the closed sets ALIGN_VALUES / JUSTIFY_VALUES. */
.fv-items-start { align-items: flex-start }
.fv-items-center { align-items: center }
.fv-items-end { align-items: flex-end }
.fv-items-stretch { align-items: stretch }
.fv-items-baseline { align-items: baseline }
.fv-justify-start { justify-content: flex-start }
.fv-justify-center { justify-content: center }
.fv-justify-end { justify-content: flex-end }
.fv-justify-between { justify-content: space-between }
.fv-justify-around { justify-content: space-around }
.fv-justify-evenly { justify-content: space-evenly }

/* The flex claim (§20.7 `grow`/`fixed`). `fv-shrink` mirrors the web shell's flex-shrink parity fix:
   a truncating caption beside a growing title must be allowed to shrink, or it starves the title to
   zero width (the Android Row defect, `android-row-caption-starves-weighted-title`). */
.fv-grow { flex: 1 1 auto }
.fv-shrink { flex: 0 1 auto; min-width: 0 }
.fv-nogrow { flex: 0 0 auto }
.fv-fixed { flex: 0 0 auto }

.fv-spacer {
  flex: 0 0 auto;
}

.fv-divider {
  border: none;
  border-top: 1px solid var(--fv-border);
  margin: 32px 0;
  width: 100%;
}

/* ---- Typography (§13 text variants) ------------------------------------------------------ */

/* Every text node carries `.fv-text` plus `.fv-text-{variant}`. The margin reset is on the base
   class so a variant rule only states the spacing it wants — the browser's default heading margins
   would otherwise fight the container `gap` that actually spaces this layout. */
.fv-text {
  margin: 0;
  min-width: 0;
}

.fv-text-title {
  font-size: 1.875rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.fv-text-subtitle {
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--fv-text-secondary);
}

.fv-text-heading {
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.25;
}

.fv-text-label {
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25;
  text-transform: none;
}

.fv-text-body {
  font-size: 1rem;
  line-height: 1.625;
}

.fv-text-caption {
  font-size: 0.875rem;
  line-height: 1.5;
}

.fv-text-micro {
  font-size: 0.75rem;
  line-height: 1.5;
}

.fv-text-code,
.fv-mono {
  font-family: var(--fv-font-mono);
  font-size: 0.875rem;
}

.fv-weight-regular { font-weight: 400 }
.fv-weight-medium { font-weight: 500 }
.fv-weight-semibold { font-weight: 600 }
.fv-weight-bold { font-weight: 700 }

.fv-align-start { text-align: start }
.fv-align-center { text-align: center }
.fv-align-end { text-align: end }

.fv-strike { text-decoration: line-through }
.fv-italic { font-style: italic }
/* `muted` (§20.6) is reduced OPACITY, not a color swap — the same tunable the Web Shell
 * (`--fabric-muted`) and the native shell (`tokens.opacity("muted")`) render it from. This rule used
 * to recolor to `text-secondary` instead, which is a different treatment (and one that says nothing
 * about a muted non-text node); no page emitted the flag yet, so nothing regresses in changing it. */
.fv-muted { opacity: var(--fv-muted) }
.fv-selected { color: var(--fv-accent) }

/* Line clamp (§13 `lines`, and `style.truncate` → fv-lines-1). `-webkit-line-clamp` is the only
   cross-browser clamp; it is implemented everywhere including Firefox despite the prefix. */
.fv-lines-1,
.fv-lines-2,
.fv-lines-3,
.fv-lines-4,
.fv-lines-5,
.fv-lines-6 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.fv-lines-1 { -webkit-line-clamp: 1 }
.fv-lines-2 { -webkit-line-clamp: 2 }
.fv-lines-3 { -webkit-line-clamp: 3 }
.fv-lines-4 { -webkit-line-clamp: 4 }
.fv-lines-5 { -webkit-line-clamp: 5 }
.fv-lines-6 { -webkit-line-clamp: 6 }

/* Whitespace keys (§20.7 `wrap`). */
.fv-pre { white-space: pre }
.fv-pre-line { white-space: pre-line }
.fv-nowrap { white-space: nowrap }

/* Screen-reader-only text — the `a11y.hint` target the serializer emits with a generated
   `fv-hint-{n}` id. Clipped rather than `display:none`, which would remove it from the a11y tree
   and defeat the `aria-describedby` that points at it. */
.fv-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Color / surface tokens (§20.7 background, color, radius, border, shadow) ------------- */

.fv-bg-base { background: var(--fv-bg-base) }
.fv-bg-primary { background: var(--fv-bg-primary) }
.fv-bg-secondary { background: var(--fv-bg-secondary) }
/* `--fv-text-inverse` and not `#fff`: the inverse token is white in the light scheme and near-black
   in the dark one, because the dark accent is a light jade. White on it is 2.21:1 — an AA failure the
   generator's contrast check could not see while the value was a literal rather than a token. */
.fv-bg-accent { background: var(--fv-accent); color: var(--fv-text-inverse) }
.fv-bg-none { background: transparent }

.fv-fg-primary { color: var(--fv-text-primary) }
.fv-fg-secondary { color: var(--fv-text-secondary) }
.fv-fg-text-primary { color: var(--fv-text-primary) }
.fv-fg-text-secondary { color: var(--fv-text-secondary) }
.fv-fg-accent { color: var(--fv-accent) }

.fv-radius-none { border-radius: var(--fv-radius-none) }
.fv-radius-sm { border-radius: var(--fv-radius-sm) }
.fv-radius-md { border-radius: var(--fv-radius-md) }
.fv-radius-lg { border-radius: var(--fv-radius-lg) }
.fv-radius-xl { border-radius: var(--fv-radius-xl) }
.fv-radius-2xl { border-radius: var(--fv-radius-2xl) }
.fv-radius-full { border-radius: var(--fv-radius-full) }

.fv-border-none { border: none }
.fv-border-all { border: 1px solid var(--fv-border) }
.fv-border-top { border-top: 1px solid var(--fv-border) }
.fv-border-bottom { border-bottom: 1px solid var(--fv-border) }
.fv-border-left { border-left: 3px solid var(--fv-border) }
.fv-border-right { border-right: 1px solid var(--fv-border) }

/* Shadows are kept subtle and few: a static document has no elevation hierarchy to express, only
   the occasional lifted card on the landing page. The values are the scale's, per scheme — a shadow
   is not scheme-independent, and one neutral-black set served to both meant a lifted card had no
   visible edge in dark mode, where the same 8% black falls on an almost-black page. */
.fv-shadow-none { box-shadow: none }
.fv-shadow-sm { box-shadow: var(--fv-shadow-sm) }
.fv-shadow-md { box-shadow: var(--fv-shadow-md) }
.fv-shadow-lg { box-shadow: var(--fv-shadow-lg) }

/* ---- Links and buttons ------------------------------------------------------------------- */

.fv-link {
  color: var(--fv-accent);
  text-decoration: none;
}

.fv-link:hover,
.fv-link:focus-visible {
  text-decoration: underline;
}

/* A visible focus ring on every focusable thing. The anonymous pages are the surface most likely to
   be read by keyboard and assistive tech, and `outline: none` with no replacement is the single most
   common accessibility regression in a hand-written stylesheet. */
.fv-link:focus-visible,
.fv-disclosure > summary:focus-visible {
  outline: 2px solid var(--fv-accent);
  outline-offset: 2px;
  border-radius: var(--fv-radius-sm);
}

/* Link `variant`/`size` (fv-btn-*) — the call-to-action forms the landing and pricing pages use. */
.fv-btn-primary,
.fv-btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: var(--fv-radius-full);
  font-weight: 600;
  text-decoration: none;
  /* No `transition`: the reduced-motion rule at the bottom would have to override it, and a static
     page's buttons gain nothing from an animated hover. */
}

.fv-btn-primary {
  background: var(--fv-accent);
  color: var(--fv-text-inverse);
}

.fv-btn-primary:hover,
.fv-btn-primary:focus-visible {
  /* A filled button must not underline on hover — the underline reads as a rendering fault on a
     solid pill. Moving the surface is the affordance instead.
     `--fv-accent-hover` and not `filter: brightness(0.93)`: brightness always DARKENS, which is the
     wrong direction in a scheme whose accent is already light — the button dimmed toward the page on
     hover. The token is the scale's own step-10, so it moves toward the text end in either scheme. */
  text-decoration: none;
  background: var(--fv-accent-hover);
}

.fv-btn-primary:active {
  background: var(--fv-accent-pressed);
}

.fv-btn-secondary {
  background: transparent;
  color: var(--fv-text-primary);
  border: 1px solid var(--fv-border);
}

.fv-btn-secondary:hover,
.fv-btn-secondary:focus-visible {
  text-decoration: none;
  border-color: var(--fv-accent);
  color: var(--fv-accent);
}

.fv-btn-sm { padding: 8px 14px; font-size: 0.875rem }
.fv-btn-md { padding: 12px 20px }
.fv-btn-lg { padding: 16px 28px; font-size: 1.125rem }

/* ---- Email capture ------------------------------------------------------------------------
   The `emailcapture` kind (`fvhtml::Serializer::email_capture_node`) — one label, one field, one
   submit. Its label reuses `.fv-text-label`, its hint `.fv-text-caption .fv-muted`, and its button
   the `.fv-btn-*` pill above, so only the two parts with no existing equivalent are styled here.

   Laid out with `flex-wrap` rather than a grid: the field and the pill sit side by side where there
   is room and stack where there is not, which is the whole responsive requirement for three
   controls. */

.fv-emailcapture {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  /* The label is a flex ITEM, so it needs a full row to itself above the field — otherwise the three
     controls sit in one line and the label reads as a prefix to the input rather than its name. */
  max-width: var(--fv-measure);
}

.fv-emailcapture > .fv-text-label {
  flex: 0 0 100%;
  margin: 0;
}

/* The hint is also a full-width row, and it follows the controls in the DOM (an `aria-describedby`
   target, so its position is a visual choice and not a reading order). */
.fv-emailcapture > .fv-text-caption {
  flex: 0 0 100%;
  margin: 0;
}

.fv-emailcapture-field {
  /* Grows to fill the row; `min-width` rather than a fixed basis so a narrow viewport wraps the pill
     below instead of squeezing an email field to a few characters. */
  flex: 1 1 16rem;
  min-width: 0;
  padding: 12px 14px;
  border: 1px solid var(--fv-border);
  border-radius: var(--fv-radius-md);
  background: var(--fv-bg-primary);
  color: var(--fv-text-primary);
  /* `font: inherit` and not a size: a form control does not inherit the document font by default, and
     an email field set in the browser default face is the one element on the page that looks pasted
     in from somewhere else. */
  font: inherit;
}

.fv-emailcapture-field:focus-visible {
  outline: 2px solid var(--fv-accent);
  outline-offset: 2px;
  border-color: var(--fv-accent);
}

.fv-emailcapture-submit {
  /* The `.fv-btn-primary` pill supplies the surface, the radius and the weight; these are the button
     element's own resets, which an `<a>` never needed. `cursor` included because a `<button>` does
     not get the pointer by default and the pill reads as a link. */
  border: none;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
}

/* ---- Images ------------------------------------------------------------------------------ */

.fv-image {
  max-width: 100%;
  height: auto;
  display: block;
}

.fv-fit-cover { object-fit: cover }
.fv-fit-contain { object-fit: contain }
.fv-fit-fill { object-fit: fill }

.fv-shape-circle { border-radius: var(--fv-radius-full) }
.fv-shape-rounded { border-radius: var(--fv-radius-md) }
.fv-shape-square { border-radius: 0 }

/* ---- Disclosure -------------------------------------------------------------------------- */

.fv-disclosure {
  border: 1px solid var(--fv-border);
  border-radius: var(--fv-radius-md);
  padding: 12px 16px;
}

.fv-disclosure > summary {
  cursor: pointer;
  font-weight: 600;
  /* `list-style` for standards browsers; `::-webkit-details-marker` for Safari, which ignores it. */
  list-style: none;
}

.fv-disclosure > summary::-webkit-details-marker {
  display: none;
}

.fv-disclosure > summary::after {
  content: "+";
  float: right;
  color: var(--fv-text-secondary);
}

.fv-disclosure[open] > summary::after {
  content: "\2212"; /* MINUS SIGN — visually matched to the "+" it replaces, unlike a hyphen. */
}

/* ---- The framed support panel ------------------------------------------------------------- */

/* A `<details>` docking one same-origin `<iframe src="/support-panel">` bottom-right, emitted by the
   edge serializer (`crates/http-edge/src/fvhtml.rs::support_panel_markup`) on the pages whose
   frontmatter — or whose scope default — asks for it. Customer Support §3.2A.

   IT IS A `<details>` BECAUSE THERE IS NO SCRIPT. A published page is served under
   `default-src 'none'` with no `script-src` at all, so the open/close state has to be the browser's
   own, and everything below is CSS over that one built-in toggle. Nothing here may come to depend on
   a class the page cannot add without JS.

   The three rules that carry the behavior: `position: fixed` so the affordance survives a scroll on a
   long help article; `[open]` turning the pill into the frame's title bar rather than leaving a pill
   floating over its own panel; and the narrow-viewport arm giving the frame the full width, because a
   380px dock on a 360px phone is a panel with its right edge off-screen.

   AND THE ✕ IS HERE, on the `[open]` title bar, for the no-script reason above. It cannot live in the
   framed element's own tree: that tree renders inside the `<iframe>`, and nothing inside a frame can
   collapse the `<details>` around it without script. The panel used to draw one there (from
   `support_chat/render`, which read the slot-injected `parent_kernel_urn` as "docked") and it was
   visibly dead — a close button that closed nothing. Putting the glyph on the `<summary>` makes it the
   BROWSER's own toggle: it is part of the control a click already closes, so it cannot come apart from
   the behavior it advertises. `content` on `::after`, not markup, so `support_panel_markup` stays a
   label and a frame. */

.fv-support-panel {
  position: fixed;
  right: 16px;
  bottom: 16px;
  /* Below the focused skip link (`.fv-role-skip-link:focus`, z-index 10) — the only other fixed thing
     on the page. They occupy opposite corners, so this is about the ordering being STATED rather than
     about a collision: a keyboard user's first tab stop must never land under a chat pill. */
  z-index: 9;
  max-width: calc(100% - 32px);
  font-family: var(--fv-font-sans);
}

.fv-support-panel-launch {
  /* Flex, not block: the `[open]` ✕ below is a `::after` on this same element, and the title bar wants
     it on the trailing edge with the label holding the rest. Closed there is no `::after`, so the pill
     is a lone flex item and sizes exactly as it did. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  cursor: pointer;
  /* `list-style` for standards browsers; `::-webkit-details-marker` for Safari, which ignores it. The
     same pair `.fv-disclosure > summary` needs, for the same reason. */
  list-style: none;
  padding: 10px 18px;
  border-radius: var(--fv-radius-full);
  background: var(--fv-accent);
  color: var(--fv-text-inverse);
  font-size: 0.9375rem;
  font-weight: 600;
  box-shadow: var(--fv-shadow-md);
}

.fv-support-panel-launch::-webkit-details-marker {
  display: none;
}

.fv-support-panel-launch:hover {
  background: var(--fv-accent-hover);
}

/* Open, the label is the panel's title bar: square across the bottom so it meets the frame, and no
   shadow of its own now that the frame below carries one for both. */
.fv-support-panel[open] > .fv-support-panel-launch {
  border-radius: var(--fv-radius-lg) var(--fv-radius-lg) 0 0;
  box-shadow: none;
}

/* The close affordance. `[open]` only: on the closed pill a ✕ reads as "dismiss this pill", which the
   toggle does not do. U+2715 MULTIPLICATION X, the same glyph the docked panel's own button carries, so
   the two surfaces close under one mark. */
.fv-support-panel[open] > .fv-support-panel-launch::after {
  content: "\2715";
  /* Smaller than the label and NOT dimmed. A reduced opacity would be a literal here — de-emphasis has
     exactly one source in this sheet (`--fv-muted`, see `.fv-muted`) — and the ✕ is the control's only
     other half, so size is the right way to subordinate it to the title. */
  font-size: 0.8125rem;
  /* The glyph's own box sits high in the line otherwise, above the label's cap height. */
  line-height: 1;
}

.fv-support-panel-frame {
  display: block;
  width: 380px;
  max-width: 100%;
  height: 520px;
  /* Never taller than the viewport it is pinned inside, allowing for the title bar and the bottom
     offset — otherwise the top of the conversation is unreachable on a short window. */
  max-height: calc(100vh - 96px);
  border: 1px solid var(--fv-border);
  border-radius: 0 0 var(--fv-radius-lg) var(--fv-radius-lg);
  background: var(--fv-bg-primary);
  box-shadow: var(--fv-shadow-lg);
}

@media (max-width: 40rem) {
  .fv-support-panel {
    right: 8px;
    left: 8px;
    bottom: 8px;
    max-width: none;
  }

  .fv-support-panel-frame {
    width: auto;
    height: 70vh;
  }
}

/* A printed page cannot be asked a question. Hidden for the same reason the nav and footer are
   (see `_layouts`'s print block) — and a legal document actually does get printed and filed. */
@media print {
  .fv-support-panel {
    display: none;
  }
}

/* ---- Prose (the `native` markdown bridge) ------------------------------------------------ */

/* `.fv-prose` wraps the output of `fallbackpage::render_markdown_body`, so its descendants are plain
   Markdown-generated tags with no classes. These are the only element selectors in this file, and
   they are scoped under `.fv-prose` so they cannot reach the composed node tree around them.

   THE TYPOGRAPHY BELOW IS PORTED FROM PICO CSS v2.1.1 (https://picocss.com), Copyright 2019-2025,
   MIT licensed. It ports at all because Pico is CLASSLESS: it styles bare semantic tags, which is
   exactly what the Markdown bridge emits, so its rules transfer by prefixing `.fv-prose` — there is
   no markup contract to satisfy. What was taken is the single-unit vertical-rhythm model, the
   heading scale with its proportional top spacing, and the table / code / blockquote treatment.
   What was NOT taken: Pico's palette (the tokens here are the brand's, and the accent is gated by
   `pageaudit::every_brand_asset_uses_the_accent_token`), its font stack, and its component and form
   CSS — prose contains no forms.

   Four deliberate divergences from the source are marked `DIVERGES` at the rule that makes them.

   Every selector is still one the renderer can actually emit. `render_markdown_body` is
   pulldown-cmark with tables + strikethrough + footnotes and raw HTML escaped to text, so there are
   deliberately NO rules for `dl`, `mark`, `kbd`, or `small`: nothing can produce those tags, and a
   rule for one would be dead weight that reads as supported. */

/* ONE rhythm unit drives every vertical margin in the prose, which is the whole of Pico's spacing
   model: paragraphs, lists, tables, code blocks and headings all resolve to multiples of the same
   beat. The rules this replaced used an unrelated mix of 40px / 32px / 28px / 24px / 16px / 12px /
   8px / 6px, so no two block types agreed on a baseline and the page had no rhythm to read. */
.fv-prose {
  --fv-prose-rhythm: 1rem;
  /* Inline code needs a fill that survives WITHOUT a border (see `.fv-prose code`), and
     `--fv-bg-secondary` is not strong enough: #FAF9F8 against a #FDFCFC page is invisible at
     0.875em. `--fv-bg-tertiary` is the scale's step-3 — the "UI element background" step, which
     exists for exactly this (wells, inputs, code fills) and is a shade stronger. The alias is kept
     because it names the ROLE this prose run wants rather than the step it resolves to, and because
     it is read in two places below; the dark arm it used to need is gone, since the token carries
     its own scheme. */
  --fv-prose-code-bg: var(--fv-bg-tertiary);
}

.fv-prose > :first-child {
  margin-top: 0;
}

.fv-prose > :last-child {
  margin-bottom: 0;
}

/* Every block ends on the rhythm and none carries a top margin. Top space is added back in exactly
   one place — a heading that FOLLOWS something — which is what keeps the beat from doubling up
   wherever two block types meet. */
.fv-prose p,
.fv-prose ul,
.fv-prose ol,
.fv-prose pre,
.fv-prose table,
.fv-prose blockquote {
  margin-top: 0;
  margin-bottom: var(--fv-prose-rhythm);
}

/* The heading scale is Pico's (2 / 1.75 / 1.5 / 1.25 / 1.125 / 1rem) SHIFTED DOWN ONE RUNG.
   DIVERGES, and it has to: the page's own H1 is composed ABOVE the prose as `.fv-text-title` at
   1.875rem, so Pico's h2 at 1.75rem would land a hair under the page title and read as a second
   one. A body `##` is the document's main sectioning level, so h2 is the rung that must sit clearly
   below the title — at 1.5rem it does, and every rung under it keeps Pico's ratios. Line height
   tightens as size grows, which is Pico's rule as well: display type needs less leading, not more. */
.fv-prose h1,
.fv-prose h2,
.fv-prose h3,
.fv-prose h4,
.fv-prose h5,
.fv-prose h6 {
  margin-top: 0;
  margin-bottom: var(--fv-prose-rhythm);
  font-weight: 700;
}

.fv-prose h1 { font-size: 1.75rem; line-height: 1.15 }
.fv-prose h2 { font-size: 1.5rem; line-height: 1.175 }
.fv-prose h3 { font-size: 1.25rem; line-height: 1.2 }
.fv-prose h4 { font-size: 1.125rem; line-height: 1.225 }
.fv-prose h5 { font-size: 1.0625rem; line-height: 1.25 }
.fv-prose h6 { font-size: 1rem; line-height: 1.25 }

/* Pico's best idea, and the reason h2 no longer needs a `border-bottom` to mark a section: a heading
   gets top space only when it FOLLOWS a block, and the amount is proportional to its own size (1.5x,
   exactly the source's ratio). So the first heading of a document sits tight under the composed
   title, every later one opens a gap sized to its rank, and two stacked headings stay together as a
   pair. Hierarchy is carried by space rather than by a rule across the measure.

   ORDER IS LOAD-BEARING. `.fv-prose :where(…) ~ h2` and `.fv-prose h2` have IDENTICAL specificity —
   0,1,1, since `:where()` contributes nothing — so these six win only by coming LAST. Moved above
   the block that sets `margin-top: 0`, they would all silently stop applying. This is the same
   equal-specificity trap the dark-scheme arm at the end of this file exists to avoid. */
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h1 { margin-top: 2.625rem }
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h2 { margin-top: 2.25rem }
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h3 { margin-top: 1.875rem }
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h4 { margin-top: 1.6875rem }
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h5 { margin-top: 1.5rem }
.fv-prose :where(blockquote, ol, p, pre, table, ul) ~ h6 { margin-top: 1.5rem }

/* `square` is Pico's marker for level 1. The DEPTH CYCLE below is not Pico's, and it is the point of
   these three rules: the browser default cycles disc → circle → disc, so a list nested three deep
   marks its outermost and innermost items identically, and the only remaining cue for depth is the
   indent — which this file already halves to 24px (see the rule below). Three distinct shapes, so
   depth reads from the marker as well as from the indent.
   `.fv-prose li > ul` further down is the other half of the same assumption: nested lists happen.

   Level 4+ keeps `disc` rather than cycling back to `square`, so the ambiguity that returns is
   between two levels three apart rather than the adjacent pair the browser default confuses. Nothing
   published nests that far; a document that did would want restructuring, not a fourth marker.

   `list-style-type` and not the `list-style` shorthand: the shorthand also resets
   `list-style-position` and `-image`, so a later `position: inside` on a `ul` would be silently
   clobbered by a rule that reads as if it only chose a shape. Specificity rises with depth
   (0,1,2 → 0,1,3 → 0,1,4), so these three are order-independent. */
.fv-prose ul li {
  list-style-type: square;
}

.fv-prose ul ul li {
  list-style-type: circle;
}

.fv-prose ul ul ul li {
  list-style-type: disc;
}

/* The same defect on the ordered side, and worse: the browser default is `decimal` at EVERY depth, so
   a nested clause list renders "1." under "1." with only the indent to separate them — in the one
   corpus (the legal documents) where a reader may need to cite the level they are reading. The
   decimal → lower-alpha → lower-roman cycle is the convention those documents already use in prose
   ("§4(a)(ii)"), which is the argument for it over any other ordering. */
.fv-prose ol ol li {
  list-style-type: lower-alpha;
}

.fv-prose ol ol ol li {
  list-style-type: lower-roman;
}

.fv-prose ul,
.fv-prose ol {
  /* DIVERGES: Pico leaves the browser's ~40px indent. Held to 24px because the document layouts hold
     prose to a 46rem measure, where a 40px indent reads as a block quote rather than as a list. */
  padding-left: 24px;
}

.fv-prose li {
  margin-bottom: calc(var(--fv-prose-rhythm) * 0.25);
}

/* A nested list belongs to the item above it, so it opens only a quarter beat and closes none.
   Selected through `li >` rather than Pico's `:where(ol, ul) :where(ol, ul)`: that spelling is
   specificity 0,1,0 and would LOSE to `.fv-prose ul` (0,1,1) above, silently keeping the parent's
   full bottom margin. `li > ul` is 0,1,2 and wins wherever it sits in the file. */
.fv-prose li > ul,
.fv-prose li > ol {
  margin: calc(var(--fv-prose-rhythm) * 0.25) 0 0;
}

.fv-prose a {
  color: var(--fv-accent);
  /* DIVERGES from what this replaced, TOWARD Pico: links are underlined at rest, not only on hover.
     Colour alone is not a sufficient cue (WCAG 1.4.1 Use of Color), and accent-green against body
     text on a white page is precisely the pairing that fails it for a red-green colour-blind reader.
     The offset is Pico's, and keeps the rule clear of descenders. */
  text-decoration: underline;
  text-underline-offset: 0.1rem;
  /* Long URLs and support addresses appear as link text in the legal documents. Without this a
     single unbreakable token overflows the measure and scrolls the page sideways on a phone. */
  overflow-wrap: anywhere;
}

/* Hover/focus can no longer ADD the underline, since it is now always present — so it thickens it
   instead. Thickness, not a colour change: the accent is the same token in both schemes. */
.fv-prose a:hover,
.fv-prose a:focus-visible {
  text-decoration-thickness: 2px;
}

.fv-prose strong {
  font-weight: 600;
}

/* DIVERGES: the border is dropped, following Pico, which gives inline code a fill and a radius and
   no outline. At 0.875em a 1px box around two words reads as an input field; the fill alone reads as
   code. That is what `--fv-prose-code-bg` above exists for. */
.fv-prose code {
  font-family: var(--fv-font-mono);
  font-size: 0.875em;
  background: var(--fv-prose-code-bg);
  border-radius: var(--fv-radius-sm);
  padding: 0.125rem 0.25rem;
}

.fv-prose pre {
  background: var(--fv-prose-code-bg);
  border: 1px solid var(--fv-border);
  border-radius: var(--fv-radius-md);
  padding: var(--fv-prose-rhythm);
  overflow-x: auto;
}

/* Fill, radius and padding all live on `pre`, so the inner `code` resets to plain text. Pico puts
   the padding on `pre > code` instead; keeping it on `pre` means a fenced block the renderer emits
   without an inner `code` is still padded rather than flush against its own border. */
.fv-prose pre code {
  background: none;
  border-radius: 0;
  padding: 0;
  font-size: inherit;
}

/* Pico's bar is 0.25rem and its padding a full beat on all sides — heavier and roomier than a
   hairline, which is what stops a set-apart passage from reading as an indented paragraph.
   DIVERGES in one respect: the text is NOT muted. It was, and in a legal document muting the one
   passage the author chose to set apart de-emphasises exactly the wrong thing. */
.fv-prose blockquote {
  padding: var(--fv-prose-rhythm);
  border-left: 0.25rem solid var(--fv-border);
}

/* The pricing and comparison tables, and the largest single visual change in this port:
   HORIZONTAL RULES ONLY. Every cell used to carry a full 1px box, which renders a comparison table
   as a spreadsheet grid; Pico gives each row one bottom rule and lets the columns be defined by
   their alignment instead. The header's rule is three times heavier (Pico's `0.1875rem`), which is
   what separates the header band without needing a fill behind it. */
.fv-prose table {
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
  font-size: 0.9375rem;
  /* `display: block` + `overflow-x: auto` on the TABLE, not on a wrapper: the Markdown renderer
     emits a bare `<table>` with nothing around it to become the scroll container, so the table has
     to be its own. `table-layout` therefore stays auto and cells are allowed to wrap. */
  display: block;
  overflow-x: auto;
}

.fv-prose th,
.fv-prose td {
  padding: calc(var(--fv-prose-rhythm) / 2) var(--fv-prose-rhythm);
  border: none;
  border-bottom: 1px solid var(--fv-border);
  text-align: left;
  vertical-align: top;
}

.fv-prose thead th {
  border-bottom-width: 0.1875rem;
  font-weight: 600;
}

/* DIVERGES: Pico's `hr` margin is one rhythm unit. Doubled here, because in these documents a
   thematic break separates SECTIONS, and headings now open 2.25rem above themselves — at one beat
   the break would sit tighter than the gap around the heading following it, inverting what the two
   marks tell the reader about the size of the seam. */
.fv-prose hr {
  height: 0;
  margin: calc(var(--fv-prose-rhythm) * 2) 0;
  border: none;
  border-top: 1px solid var(--fv-border);
}

.fv-prose img {
  max-width: 100%;
  height: auto;
}

/* ---- Presentational roles (§20.7 `style.role`) ------------------------------------------- */

/* These are the composition lambda's own vocabulary — `tlnk_root/fabric/site/page/render.star`
   sets each one. A role with no rule here renders unstyled, so this list and that lambda's roles
   must move together. */

/* The bypass link (WCAG 2.4.1, Level A) — first in the tab order, hidden until it has focus.
   Clipped exactly like `.fv-sr-only` rather than `display:none`, which would take it out of the tab
   order and so remove the very affordance it provides. On focus it becomes a real, visible target
   pinned to the top-left, because a keyboard user has to SEE where the focus went. */
.fv-role-skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.fv-role-skip-link:focus,
.fv-role-skip-link:focus-visible {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 10;
  width: auto;
  height: auto;
  margin: 0;
  padding: 8px 16px;
  overflow: visible;
  clip-path: none;
  background: var(--fv-bg-base);
  color: var(--fv-accent);
  border: 1px solid var(--fv-accent);
  border-radius: var(--fv-radius-sm);
  font-size: 0.9375rem;
  text-decoration: none;
}

/* ---- The header and footer bands --------------------------------------------------------- */

/* Two elements per band, and the reason is the one visual detail that separates a product site from a
   styled document: the surface and the rule reach the WINDOW edge while the content stays on the page
   frame.

   The outer element is a direct child of <body>, so it is full width by default and needs no
   `100vw` (which overflows by the scrollbar's width on a desktop browser) and no pinned
   pseudo-element. The inner is what carries `--fv-frame`.

   `flex-shrink: 0`: <body> is a flex column, and a band whose content wraps onto two rows would
   otherwise be compressed by the `flex: 1` on `.fv-page` beside it. */
.fv-role-site-header,
.fv-role-site-footer {
  flex-shrink: 0;
  width: 100%;
}

/* A surface distinct from the page plus the rule under it. Both, not just the rule: on a page scrolled
   to the top the rule alone is ambiguous — it could be a heading underline. The tint says "chrome".
   `--fv-bg-primary` reads as raised above `--fv-bg-base` in BOTH schemes, which is why it is the token
   here rather than a literal. */
.fv-role-site-header {
  background: var(--fv-bg-primary);
  border-bottom: 1px solid var(--fv-border);
}

/* The frame, shared with `.fv-page` so the wordmark's left edge and the article's left edge line up.
   The horizontal padding must match `.fv-page`'s for that to hold — the two values move together. */
.fv-role-site-header-inner,
.fv-role-site-footer-inner {
  width: 100%;
  max-width: var(--fv-frame);
  margin-inline: auto;
}

.fv-role-site-header-inner {
  padding: 14px 20px;
}

/* The action pair. `margin-left: auto` is not needed — the row's `justify: between` already pushes
   this to the far edge — so this rule only keeps the pair from being the item that wraps first: the
   nav is the more compressible of the two, and the way in should be the last thing to move. */
.fv-role-site-actions {
  flex-shrink: 0;
}

/* The one emphasised control in the chrome. A filled pill, because a header CTA competing with three
   text nav links needs to win on weight rather than on colour alone — and `fv-btn-primary` already
   carries the fill, so this rule states only what makes it read as a header control: it must not grow
   to the row's height, and it must not wrap its label onto two lines. */
.fv-role-header-cta {
  white-space: nowrap;
}

.fv-role-wordmark {
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fv-text-primary);
  text-decoration: none;
}

.fv-role-wordmark:hover,
.fv-role-wordmark:focus-visible {
  color: var(--fv-accent);
  text-decoration: none;
}

.fv-role-nav-link {
  font-size: 0.9375rem;
  color: var(--fv-text-secondary);
  text-decoration: none;
}

.fv-role-nav-link:hover,
.fv-role-nav-link:focus-visible {
  color: var(--fv-accent);
  text-decoration: none;
}

/* The page you are on. Weight and full text colour, NOT the accent: the accent is what hover means
   here, and using it for the resting state of the current item would make the item you are on look
   like the one under the cursor.

   Attribute selector rather than a class, because `aria-current` is the thing that carries the meaning
   — the mark and its visual are the same fact stated once, so a nav link cannot end up looking current
   while announcing that it is not. Matches both admitted values (`page` and the section-level `true`);
   they differ in what a screen reader says, not in how strongly the item is drawn. */
.fv-role-nav-link[aria-current] {
  color: var(--fv-text-primary);
  font-weight: 600;
}

.fv-role-breadcrumbs {
  font-size: 0.875rem;
  color: var(--fv-text-secondary);
}

/* The separator is generated, not authored: putting "/" in the node tree would make it selectable
   text that a screen reader announces between every crumb. */
.fv-role-breadcrumbs > * + *::before {
  content: "/";
  margin-right: 8px;
  color: var(--fv-border);
}

.fv-role-article {
  /* The article's own children are spaced by its container gap; this only guarantees the block
     never collapses to zero height on a page whose body failed to render. */
  min-height: 1px;
}

.fv-role-pager {
  font-size: 0.9375rem;
}

/* The derived index listing (`_derived_index` in the composition lambda). Its column layout and gaps
   come from tokens in the node tree; these rules state only what a token cannot — the group heading's
   typography and the link's block presentation, which is what makes a list of titles read as an index
   rather than as a paragraph of links. */
.fv-role-index {
  margin-top: 8px;
}

/* A section heading inside the listing is a <h3> (the `heading` text variant). It sits tighter to its
   own links than the default heading rhythm, so the group reads as one unit. */
.fv-role-index-group > .fv-text-heading {
  margin: 0;
  font-size: 1.125rem;
  letter-spacing: -0.01em;
}

.fv-role-index-link {
  /* Block, so the whole row is the target — an index is navigated by pointing at a title, not at the
     few characters of it that happen to be under the cursor. */
  display: block;
  font-weight: 500;
  text-decoration: none;
}

.fv-role-index-link:hover {
  text-decoration: underline;
}

/* The footer band. Its top border comes from the node tree (`style.border: "top"`); the surface and
   the padding are here, because a band's padding belongs to its INNER wrapper and a token on the band
   would put it outside the frame.

   `margin-top: 64px` and not a margin on `.fv-page`: the gap belongs to the seam, so a page with no
   footer (there is none today, but a print stylesheet drops it) does not keep a hole where it was.
   `--fv-bg-secondary` recedes below the page in light mode and lifts in dark; either way it reads as
   a different surface, which is the whole job. */
.fv-role-site-footer {
  margin-top: 64px;
  background: var(--fv-bg-secondary);
  font-size: 0.875rem;
  color: var(--fv-text-secondary);
}

.fv-role-site-footer-inner {
  padding: 32px 20px 40px;
}

/* A footer column's caption. `label` is deliberately NOT a heading variant (§13), so it carries no
   outline weight and needs its own emphasis here to read as a column head rather than a first link. */
.fv-role-footer-heading {
  font-weight: 600;
  color: var(--fv-text-primary);
  margin-bottom: 4px;
}

/* The columns' own links sit tighter than body rhythm — a stacked list of destinations, not prose. */
.fv-role-footer-group > .fv-link {
  display: block;
  line-height: 1.9;
}

/* ---- Header wordmark image --------------------------------------------------------------- */

/* The `logo.svg` wordmark. Height only: the asset carries a viewBox, so constraining one axis keeps
   its aspect ratio without this file having to know its intrinsic size. `display: block` kills the
   inline-image baseline gap that would otherwise push the header's bottom border down by ~4px.

   The asset is scheme-aware INTERNALLY (its own `prefers-color-scheme` query) because an <img> is a
   separate document that inherits no color from this stylesheet — so there is deliberately no filter
   or opacity trick here trying to recolor it from outside. */
.fv-role-wordmark-logo {
  height: 26px;
  width: auto;
  display: block;
}

@media (max-width: 40rem) {
  .fv-role-wordmark-logo {
    height: 22px;
  }
}

/* ---- Authored block roles (the `:::` directive vocabulary) -------------------------------- */

/* `:::hero` — the tinted opening panel. Its surface, radius and padding come from tokens in the node
   tree (`background: secondary`, `radius: xl`, `padding: xl` — bare token names; the serializer adds
   the `fv-bg-` family prefix), so this rule states only what a token cannot.

   THE DARK-MODE RULE IS LOAD-BEARING, not a refinement. In dark, `--fv-bg-secondary` (#1A1918) and
   `--fv-bg-primary` are the same value and both sit within a shade of `--fv-bg-base` (#121110) — so
   the tinted panel that carries the whole hero would be invisible, and the page would silently
   render as if the block were missing. A hairline border plus a lift off the base gives it an edge in
   both schemes rather than relying on fill contrast that only exists in one. */
.fv-role-hero-panel {
  border: 1px solid var(--fv-border);
}

@media screen and (prefers-color-scheme: dark) {
  .fv-role-hero-panel {
    /* Slightly LIGHTER than bg-base, which is how elevation reads in a dark scheme (in light it
       reads as a recess). `--fv-bg-tertiary` is the step that means that — it was an authored value
       one shade off it, which is the divergence this file used to accumulate one panel at a time. */
    background: var(--fv-bg-tertiary);
  }
}

/* The hero's lead paragraph is the page's opening claim, so it is set larger than body prose. The
   `.fv-prose` descendant selector is how a prose run inside the panel is reached — the markdown
   bridge emits plain <p>, which carries no class of its own. */
.fv-role-hero-panel > .fv-prose > p:first-child {
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--fv-text-secondary);
}

/* The button row. `margin-top` rather than a larger container gap so the note line below stays
   tight to the buttons it qualifies. */
.fv-role-hero-actions {
  margin-top: 4px;
}

/* A hero CTA past the button limit renders as an ordinary link (the composer drops its `variant`),
   so it needs the inline-link affordance back — without it, a third action would read as inert text
   sitting beside two buttons. */
.fv-role-hero-cta:not([class*="fv-btn-"]) {
  align-self: center;
  font-weight: 500;
}

/* `:::features` — the claim grid. The cards' radius, border and padding come from tokens; the grid's
   column count and collapse behavior come from `.fv-grid`, so nothing here repeats them.

   The wrapper carries the block's own vertical rhythm — the same job `.fv-role-plans` does, and the
   reason it needs a rule at all: a role the serializer emits with no rule behind it is exactly what
   `every_class_the_real_pages_emit_is_styled` (pageaudit.rs) exists to reject, because the class is
   emitted silently and the block just renders unspaced. */
.fv-role-features {
  margin: 8px 0;
}

.fv-role-feature-card {
  background: var(--fv-bg-primary);
}

/* A card's heading is a real subsection heading (it replaces a `## ` or a bold list lead-in), so it
   keeps outline weight — but it must not carry the body's heading margins inside a padded card. */
.fv-role-feature-card > .fv-text-heading {
  margin: 0;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
}

/* The card's prose is a short supporting sentence, not a document section: no top margin on its
   first paragraph and no bottom margin on its last, so the card's own padding is the only inset. */
.fv-role-feature-card .fv-prose > p:first-child {
  margin-top: 0;
}

.fv-role-feature-card .fv-prose > p:last-child {
  margin-bottom: 0;
}

/* `:::callout` — an admonition. The left border carries the tone; the tone classes below only
   recolor it, so a callout with an unrecognized tone still reads as a callout. */
.fv-role-callout {
  border: 1px solid var(--fv-border);
  border-left: 3px solid var(--fv-accent);
  border-radius: var(--fv-radius-md);
  background: var(--fv-bg-secondary);
  padding: 16px;
}

/* The three tones. Deliberately NOT signalled by color alone (WCAG 1.4.1): a `warn` is authored
   with a title, and its stronger border weight is visible in a monochrome print of a legal page. */
.fv-role-callout-note {
  border-left-color: var(--fv-text-secondary);
}

/* The warning family's TEXT step, not its solid. The rule has to be seen against the callout's own
   fill, and the solid step is 2.61:1 there while the text step is 4.96:1 — the text step is the one
   the scale designs for contrast. It replaces two authored oranges that matched no token in the
   system, and it carries its own dark value, so the scheme override this rule used to need is gone.

   Spelled `warning-text` because that is the ONE name the emitter gives it. It was `--fv-warning`
   here while every shell read `--fabric-warning-text` off the same artifact field, which is exactly
   the drift a hand-typed second table produces: the rule was legal CSS reading a property this
   stylesheet no longer declares, so the border fell back to the shorthand's own color. */
.fv-role-callout-warn {
  border-left-width: 4px;
  border-left-color: var(--fv-warning-text);
}

.fv-role-callout-tip {
  border-left-color: var(--fv-accent);
}

/* A callout's title uses the `label` variant, which is NOT a heading — §13 defines `label` as a
   form-field label and the serializer emits <p> for it, so a callout inside a section cannot inject
   a phantom level into the page outline. This rule is what makes it *read* as the box's title. It
   sits tight to its own body so the box reads as one unit rather than a heading plus a paragraph. */
.fv-role-callout > .fv-text-label {
  margin: 0;
  font-size: 1rem;
}

/* `:::faq` — a stack of `<details>` disclosures. The list needs no rules of its own beyond the
   separators; `.fv-disclosure` above already styles each item and its marker. */
.fv-role-faq > .fv-disclosure + .fv-disclosure {
  border-top: 1px solid var(--fv-border);
}

/* `:::steps` — a numbered walkthrough. The row gap and the column claim come from tokens in the node
   tree; these rules state only the numeral's badge, which no token can express. */
.fv-role-steps {
  margin: 8px 0;
}

.fv-role-step-number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: 0;
  border-radius: var(--fv-radius-full);
  background: var(--fv-accent);
  color: var(--fv-text-inverse);
  font-size: 0.875rem;
  font-weight: 600;
  /* The badge is a circle, so its digit must not be pushed off-center by the inherited leading. */
  line-height: 1;
}

/* A step's own label introduces the step's body rather than a page section, which is why it uses the
   non-heading `label` variant (see the callout note above) and gets its emphasis from this rule. */
.fv-role-step > * > .fv-text-label {
  margin: 0;
  font-size: 1rem;
}

/* `:::plans` — the plan comparison. The card grid collapses to one column below the phone
   breakpoint through `.fv-grid`, which is why no per-page media query appears here. */
.fv-role-plan-card {
  border: 1px solid var(--fv-border);
  border-radius: var(--fv-radius-lg);
  background: var(--fv-bg-primary);
  padding: 24px;
}

.fv-role-plan-featured {
  border-color: var(--fv-accent);
  box-shadow: var(--fv-shadow-md);
}

/* The price is the one line a reader scans for, so it is set larger than the plan name's own
   typography would suggest and tightened against the name above it. It carries the non-heading
   `body` variant — a price is a fact about the plan, not a section of the document — so every
   dimension it needs is stated HERE rather than inherited from a heading tier; `line-height`
   included, or the price would take body prose's 1.625 leading at 1.5rem. */
.fv-role-plan-price {
  margin: 0;
  color: var(--fv-text-primary);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

/* A plan's call to action is a button-styled link (`fv-btn-primary` supplies the appearance); this
   only makes it a block so it fills the card's width and lines up across the cards. */
.fv-role-plan-cta {
  display: block;
  margin-top: 8px;
  text-align: center;
}

/* Where the call to action would be, for a plan that is advertised but not yet on sale. It takes the
   CTA's block+centered geometry so the cards still line up, but deliberately NOT its button
   appearance: a button-shaped thing that cannot be pressed reads as broken, whereas a centered line
   in that slot reads as the status it is. Muted for the same reason — it is not the page's action. */
.fv-role-plan-coming-soon {
  display: block;
  margin-top: 8px;
  color: var(--fv-text-secondary);
  text-align: center;
}

/* A plan card's list is the plan's contents, not prose: tighter than the body rhythm, and without
   the outer margin a <ul> would otherwise add inside the card's own padding.

   AND ITS MARKERS SAY SOMETHING THE BULLET DID NOT. Everywhere else on the site a `-` list is a list
   of things; in a plan card it is a list of what the plan INCLUDES, which is the one question the
   page exists to answer. A bullet is neutral about that, and the two cards sit side by side — the
   second one is a plan nobody can buy yet, so a reader scanning two identical bullet columns has to
   read prose to learn which column is available. The check reads as "you get this" at a glance and
   the accent ties it to the card's own CTA.

   `::before` and not `::marker`: `content` on `::marker` is not dependable across the engines this
   page is read in, and a marker that silently stayed a bullet in one of them is the inconsistency
   this rule exists to remove. The list stays a real <ul>/<li>, so nothing about the semantics or the
   screen-reader announcement depends on the glyph — `list-style: none` drops the painted bullet
   only. The `/ ""` is CSS alternative text: where it is honored the decoration is not announced;
   where it is not, a reader hears the glyph's own name, which is accurate rather than wrong.

   The hanging indent is rebuilt by hand (`padding-left` moves to the <li> and the marker is pulled
   back into it) because `list-style: none` gives up the browser's marker box: without that a wrapped
   feature line would run back under the check instead of aligning with the text above it. */
.fv-role-plan-card .fv-prose ul {
  margin: 0;
  padding-left: 0;
  list-style: none;
}

/* `list-style-type` HERE and not only on the <ul> above, because that reset alone did not hold: the
   site's marker-depth rule sets the shape on the <li> (`.fv-prose ul li`, 0,1,2), which beats the
   value the <li> would otherwise inherit from `list-style: none` on the <ul> (0,1,1). A plan card was
   therefore painting the square marker AND the check — two markers per feature line, in the one place
   on the site where the marker is doing the talking. This selector is 0,2,2, so it wins on
   specificity and the depth rule's own `list-style-type` form is matched rather than clobbered. */
.fv-role-plan-card .fv-prose ul li {
  position: relative;
  padding-left: 1.5em;
  list-style-type: none;
}

.fv-role-plan-card .fv-prose ul li::before {
  /* Stated TWICE, and the order is load-bearing. `content: <string> / <alt>` is one declaration: an
     engine that cannot parse the alt-text form drops the whole thing, and since `list-style: none`
     above has already given up the painted bullet, that would leave the feature list with no marker
     at all — a silent, customer-facing regression on the pricing page. The plain form first is what
     such an engine keeps. */
  content: "✓";
  content: "✓" / "";
  position: absolute;
  left: 0;
  color: var(--fv-accent);
  font-weight: 600;
}

.fv-role-plans {
  margin: 8px 0;
}

/* ---- Layouts (the `fv-layout-*` body class) ---------------------------------------------- */

/* Each layout adjusts the reading column and the leading rhythm; the class is stamped on <body> from
   the layout the composition lambda resolved, so `<main>` is always reached as a descendant.

   NO LAYOUT SETS `.fv-page`'s width — see the `--fv-frame` note. What a layout chooses is how much of
   that frame its CONTENT occupies, and the choice is the same one in two shapes: a reading layout holds
   its whole article to the measure; a composed layout holds only its running text there and lets its
   blocks span the frame. Either way the header, the footer, and the left edge of the text land on the
   same pixels on all 98 pages. */

/* `landing` and `index` open with a claim: their composed blocks (the hero panel, the feature grid,
   the derived index listing) span the frame, which is what they were sized for. */
.fv-layout-landing .fv-text-title {
  font-size: 2.5rem;
  letter-spacing: -0.03em;
}

.fv-layout-landing .fv-text-subtitle,
.fv-layout-index .fv-text-subtitle {
  font-size: 1.375rem;
}

/* The running prose BETWEEN those blocks is still prose, so it is held to the same measure a document
   uses rather than to the frame — a paragraph set to the full 60rem is a ~120-character line, and the
   landing page's closing sections are ordinary reading text sitting under a full-width hero. Direct
   children only: a prose run nested inside a hero panel or a feature card is already constrained by
   the card, and capping it again would leave a short column inside a padded box. */
.fv-layout-landing .fv-role-article > .fv-prose,
.fv-layout-index .fv-role-article > .fv-prose {
  max-width: var(--fv-measure);
}

/* `marketing` — /pricing, /delete-account, and every synthesized notice (404, the OAuth outcomes;
   `chrome::NOTICE_LAYOUT`). Same rule as landing, plus the notice's own body line: a notice composes
   `text` nodes rather than a Markdown run, so it has no `.fv-prose` to catch. The plan cards, callouts
   and button rows are blocks and span the frame. */
.fv-layout-marketing .fv-role-article > .fv-prose,
.fv-layout-marketing .fv-role-article > .fv-text-body {
  max-width: var(--fv-measure);
}

/* `legal-document` and `help-article` are reading layouts: the whole article — breadcrumbs, H1, stamp,
   prose, pager — is the reading column, and a slightly looser line height because these are the longest
   pages on the site. Left-aligned within the frame rather than centred inside it, so the first
   character of the H1 sits under the first character of the wordmark exactly as it does on every other
   layout; centring the column here would trade a jumping frame for a jumping text edge. */
.fv-layout-legal-document .fv-role-article,
.fv-layout-help-article .fv-role-article {
  max-width: var(--fv-measure);
}

.fv-layout-legal-document .fv-prose,
.fv-layout-help-article .fv-prose {
  line-height: 1.7;
}

/* A legal page's effective-date stamp sits directly under the H1 and reads as metadata. */
.fv-layout-legal-document #legal-stamp {
  color: var(--fv-text-secondary);
}

@media (max-width: 40rem) {
  .fv-page {
    padding: 24px 16px 72px;
  }

  /* The bands' horizontal padding tracks `.fv-page`'s at every breakpoint — that shared value is what
     keeps the wordmark aligned over the article's first character. */
  .fv-role-site-header-inner {
    padding: 12px 16px;
  }

  .fv-role-site-footer-inner {
    padding: 28px 16px 32px;
  }

  .fv-layout-landing .fv-text-title {
    font-size: 1.875rem;
  }
}

/* Print: the nav, footer, and pager are navigation, which a printed page cannot use. Legal
   documents get printed and filed, so this is a real path rather than a nicety. */
@media print {
  .fv-role-site-header,
  .fv-role-site-footer,
  .fv-role-pager {
    display: none;
  }

  .fv-page {
    max-width: none;
    padding: 0;
  }

  /* The reading column is a screen concern: a sheet of paper already has a measure, set by its own
     margins. Leaving the cap on would print a legal document in a column narrower than the page it is
     filed on, with the right third blank.

     Every capping selector is restated in full, because a bare `.fv-role-article` would carry one class
     against their two or three and LOSE on specificity — being later in the sheet does not rescue it. */
  .fv-layout-legal-document .fv-role-article,
  .fv-layout-help-article .fv-role-article,
  .fv-layout-landing .fv-role-article > .fv-prose,
  .fv-layout-index .fv-role-article > .fv-prose,
  .fv-layout-marketing .fv-role-article > .fv-prose,
  .fv-layout-marketing .fv-role-article > .fv-text-body {
    max-width: none;
  }

  body {
    background: #fff;
    color: #000;
  }

  /* WHERE THE SHEET BREAKS. On screen a document is one continuous column and none of this exists; on
     paper the browser cuts it every ~10in wherever it happens to land, and the places it lands are
     load-bearing in the one document type this block was written for. A clause list split from the
     heading that scopes it, or a table's header row left on the previous sheet, changes what a filed
     copy appears to say — the reader of page 4 cannot see which section they are in.

     `break-*` and not the `page-break-*` aliases: the modern properties are what current engines
     implement, and an engine old enough to need the aliases predates most of this stylesheet.

     A heading avoids breaking AFTER itself, not INSIDE — a heading that must break internally has to go
     somewhere, and forbidding both leaves the engine to resolve a contradiction by ignoring one. */
  .fv-prose h1,
  .fv-prose h2,
  .fv-prose h3,
  .fv-prose h4,
  .fv-prose h5,
  .fv-prose h6,
  .fv-text-title,
  .fv-text-heading {
    break-after: avoid;
  }

  /* Blocks that lose their meaning when cut. A list ITEM is included and a whole list is not: a long
     clause list has to break somewhere, but a single item torn across sheets reads as two clauses. */
  .fv-prose li,
  .fv-prose pre,
  .fv-prose blockquote,
  .fv-prose table,
  .fv-role-callout,
  .fv-role-callout-warn,
  .fv-role-plan-card {
    break-inside: avoid;
  }

  /* A table that does break repeats its header on the next sheet, so the columns stay identified. */
  .fv-prose thead {
    display: table-header-group;
  }

  /* Two lines minimum on either side of a break. One trailing line of a paragraph, alone at the top of
     a sheet, reads as a fragment of something the reader missed. */
  .fv-prose p,
  .fv-prose li {
    orphans: 2;
    widows: 2;
  }
}

/* Motion patterns (§20.7 `style.motion`) are entry animations. Honor the OS preference by defining
   them ONLY when motion is not reduced — the opt-out direction, so a new pattern added below cannot
   accidentally ship unguarded. */
@media (prefers-reduced-motion: no-preference) {
  .fv-motion-fade {
    animation: fv-fade 240ms ease-out both;
  }

  .fv-motion-rise {
    animation: fv-rise 280ms ease-out both;
  }

  @keyframes fv-fade {
    from { opacity: 0 }
    to { opacity: 1 }
  }

  @keyframes fv-rise {
    from { opacity: 0; transform: translateY(8px) }
    to { opacity: 1; transform: none }
  }
}

/* ---- The spacing / size scales ------------------------------------------------------------ */

/* Generated from SDL §7 (`SPACE_TOKENS` in `fvhtml.rs`). The named aliases share a rule with their
   numeric step (xs=1, sm=2, md=4, lg=6, xl=8), which is why they appear as grouped selectors. */

/* gap — `full` omitted: a percentage gap is not a meaningful spacing step */
.fv-gap-0{gap:0}
.fv-gap-1,.fv-gap-xs{gap:4px}
.fv-gap-2,.fv-gap-sm{gap:8px}
.fv-gap-3{gap:12px}
.fv-gap-4,.fv-gap-md{gap:16px}
.fv-gap-5{gap:20px}
.fv-gap-6,.fv-gap-lg{gap:24px}
.fv-gap-8,.fv-gap-xl{gap:32px}
.fv-gap-10{gap:40px}
.fv-gap-12{gap:48px}
.fv-gap-px{gap:1px}
/* padding, all sides */
.fv-p-0{padding:0}
.fv-p-1,.fv-p-xs{padding:4px}
.fv-p-2,.fv-p-sm{padding:8px}
.fv-p-3{padding:12px}
.fv-p-4,.fv-p-md{padding:16px}
.fv-p-5{padding:20px}
.fv-p-6,.fv-p-lg{padding:24px}
.fv-p-8,.fv-p-xl{padding:32px}
.fv-p-10{padding:40px}
.fv-p-12{padding:48px}
.fv-p-px{padding:1px}
/* padding-top */
.fv-pt-0{padding-top:0}
.fv-pt-1,.fv-pt-xs{padding-top:4px}
.fv-pt-2,.fv-pt-sm{padding-top:8px}
.fv-pt-3{padding-top:12px}
.fv-pt-4,.fv-pt-md{padding-top:16px}
.fv-pt-5{padding-top:20px}
.fv-pt-6,.fv-pt-lg{padding-top:24px}
.fv-pt-8,.fv-pt-xl{padding-top:32px}
.fv-pt-10{padding-top:40px}
.fv-pt-12{padding-top:48px}
.fv-pt-px{padding-top:1px}
/* padding-right */
.fv-pr-0{padding-right:0}
.fv-pr-1,.fv-pr-xs{padding-right:4px}
.fv-pr-2,.fv-pr-sm{padding-right:8px}
.fv-pr-3{padding-right:12px}
.fv-pr-4,.fv-pr-md{padding-right:16px}
.fv-pr-5{padding-right:20px}
.fv-pr-6,.fv-pr-lg{padding-right:24px}
.fv-pr-8,.fv-pr-xl{padding-right:32px}
.fv-pr-10{padding-right:40px}
.fv-pr-12{padding-right:48px}
.fv-pr-px{padding-right:1px}
/* padding-bottom */
.fv-pb-0{padding-bottom:0}
.fv-pb-1,.fv-pb-xs{padding-bottom:4px}
.fv-pb-2,.fv-pb-sm{padding-bottom:8px}
.fv-pb-3{padding-bottom:12px}
.fv-pb-4,.fv-pb-md{padding-bottom:16px}
.fv-pb-5{padding-bottom:20px}
.fv-pb-6,.fv-pb-lg{padding-bottom:24px}
.fv-pb-8,.fv-pb-xl{padding-bottom:32px}
.fv-pb-10{padding-bottom:40px}
.fv-pb-12{padding-bottom:48px}
.fv-pb-px{padding-bottom:1px}
/* padding-left */
.fv-pl-0{padding-left:0}
.fv-pl-1,.fv-pl-xs{padding-left:4px}
.fv-pl-2,.fv-pl-sm{padding-left:8px}
.fv-pl-3{padding-left:12px}
.fv-pl-4,.fv-pl-md{padding-left:16px}
.fv-pl-5{padding-left:20px}
.fv-pl-6,.fv-pl-lg{padding-left:24px}
.fv-pl-8,.fv-pl-xl{padding-left:32px}
.fv-pl-10{padding-left:40px}
.fv-pl-12{padding-left:48px}
.fv-pl-px{padding-left:1px}
/* margin, all sides */
.fv-m-0{margin:0}
.fv-m-1,.fv-m-xs{margin:4px}
.fv-m-2,.fv-m-sm{margin:8px}
.fv-m-3{margin:12px}
.fv-m-4,.fv-m-md{margin:16px}
.fv-m-5{margin:20px}
.fv-m-6,.fv-m-lg{margin:24px}
.fv-m-8,.fv-m-xl{margin:32px}
.fv-m-10{margin:40px}
.fv-m-12{margin:48px}
.fv-m-px{margin:1px}
/* margin-top */
.fv-mt-0{margin-top:0}
.fv-mt-1,.fv-mt-xs{margin-top:4px}
.fv-mt-2,.fv-mt-sm{margin-top:8px}
.fv-mt-3{margin-top:12px}
.fv-mt-4,.fv-mt-md{margin-top:16px}
.fv-mt-5{margin-top:20px}
.fv-mt-6,.fv-mt-lg{margin-top:24px}
.fv-mt-8,.fv-mt-xl{margin-top:32px}
.fv-mt-10{margin-top:40px}
.fv-mt-12{margin-top:48px}
.fv-mt-px{margin-top:1px}
/* margin-right */
.fv-mr-0{margin-right:0}
.fv-mr-1,.fv-mr-xs{margin-right:4px}
.fv-mr-2,.fv-mr-sm{margin-right:8px}
.fv-mr-3{margin-right:12px}
.fv-mr-4,.fv-mr-md{margin-right:16px}
.fv-mr-5{margin-right:20px}
.fv-mr-6,.fv-mr-lg{margin-right:24px}
.fv-mr-8,.fv-mr-xl{margin-right:32px}
.fv-mr-10{margin-right:40px}
.fv-mr-12{margin-right:48px}
.fv-mr-px{margin-right:1px}
/* margin-bottom */
.fv-mb-0{margin-bottom:0}
.fv-mb-1,.fv-mb-xs{margin-bottom:4px}
.fv-mb-2,.fv-mb-sm{margin-bottom:8px}
.fv-mb-3{margin-bottom:12px}
.fv-mb-4,.fv-mb-md{margin-bottom:16px}
.fv-mb-5{margin-bottom:20px}
.fv-mb-6,.fv-mb-lg{margin-bottom:24px}
.fv-mb-8,.fv-mb-xl{margin-bottom:32px}
.fv-mb-10{margin-bottom:40px}
.fv-mb-12{margin-bottom:48px}
.fv-mb-px{margin-bottom:1px}
/* margin-left */
.fv-ml-0{margin-left:0}
.fv-ml-1,.fv-ml-xs{margin-left:4px}
.fv-ml-2,.fv-ml-sm{margin-left:8px}
.fv-ml-3{margin-left:12px}
.fv-ml-4,.fv-ml-md{margin-left:16px}
.fv-ml-5{margin-left:20px}
.fv-ml-6,.fv-ml-lg{margin-left:24px}
.fv-ml-8,.fv-ml-xl{margin-left:32px}
.fv-ml-10{margin-left:40px}
.fv-ml-12{margin-left:48px}
.fv-ml-px{margin-left:1px}
/* size axis: width. `full` is the fill sentinel — the one token here that
   is a proportion rather than a length, which is why it is kept for the
   size axes and dropped from every spacing group above */
.fv-w-0{width:0}
.fv-w-1,.fv-w-xs{width:4px}
.fv-w-2,.fv-w-sm{width:8px}
.fv-w-3{width:12px}
.fv-w-4,.fv-w-md{width:16px}
.fv-w-5{width:20px}
.fv-w-6,.fv-w-lg{width:24px}
.fv-w-8,.fv-w-xl{width:32px}
.fv-w-10{width:40px}
.fv-w-12{width:48px}
.fv-w-px{width:1px}
.fv-w-full{width:100%}
/* size axis: height */
.fv-h-0{height:0}
.fv-h-1,.fv-h-xs{height:4px}
.fv-h-2,.fv-h-sm{height:8px}
.fv-h-3{height:12px}
.fv-h-4,.fv-h-md{height:16px}
.fv-h-5{height:20px}
.fv-h-6,.fv-h-lg{height:24px}
.fv-h-8,.fv-h-xl{height:32px}
.fv-h-10{height:40px}
.fv-h-12{height:48px}
.fv-h-px{height:1px}
.fv-h-full{height:100%}
/* size axis: minWidth */
.fv-minw-0{min-width:0}
.fv-minw-1,.fv-minw-xs{min-width:4px}
.fv-minw-2,.fv-minw-sm{min-width:8px}
.fv-minw-3{min-width:12px}
.fv-minw-4,.fv-minw-md{min-width:16px}
.fv-minw-5{min-width:20px}
.fv-minw-6,.fv-minw-lg{min-width:24px}
.fv-minw-8,.fv-minw-xl{min-width:32px}
.fv-minw-10{min-width:40px}
.fv-minw-12{min-width:48px}
.fv-minw-px{min-width:1px}
.fv-minw-full{min-width:100%}
/* size axis: maxWidth */
.fv-maxw-0{max-width:0}
.fv-maxw-1,.fv-maxw-xs{max-width:4px}
.fv-maxw-2,.fv-maxw-sm{max-width:8px}
.fv-maxw-3{max-width:12px}
.fv-maxw-4,.fv-maxw-md{max-width:16px}
.fv-maxw-5{max-width:20px}
.fv-maxw-6,.fv-maxw-lg{max-width:24px}
.fv-maxw-8,.fv-maxw-xl{max-width:32px}
.fv-maxw-10{max-width:40px}
.fv-maxw-12{max-width:48px}
.fv-maxw-px{max-width:1px}
.fv-maxw-full{max-width:100%}
/* size axis: minHeight */
.fv-minh-0{min-height:0}
.fv-minh-1,.fv-minh-xs{min-height:4px}
.fv-minh-2,.fv-minh-sm{min-height:8px}
.fv-minh-3{min-height:12px}
.fv-minh-4,.fv-minh-md{min-height:16px}
.fv-minh-5{min-height:20px}
.fv-minh-6,.fv-minh-lg{min-height:24px}
.fv-minh-8,.fv-minh-xl{min-height:32px}
.fv-minh-10{min-height:40px}
.fv-minh-12{min-height:48px}
.fv-minh-px{min-height:1px}
.fv-minh-full{min-height:100%}
/* size axis: maxHeight */
.fv-maxh-0{max-height:0}
.fv-maxh-1,.fv-maxh-xs{max-height:4px}
.fv-maxh-2,.fv-maxh-sm{max-height:8px}
.fv-maxh-3{max-height:12px}
.fv-maxh-4,.fv-maxh-md{max-height:16px}
.fv-maxh-5{max-height:20px}
.fv-maxh-6,.fv-maxh-lg{max-height:24px}
.fv-maxh-8,.fv-maxh-xl{max-height:32px}
.fv-maxh-10{max-height:40px}
.fv-maxh-12{max-height:48px}
.fv-maxh-px{max-height:1px}
.fv-maxh-full{max-height:100%}
/* spacer size — a fixed basis; `.fv-spacer` supplies flex:0 0 auto */
.fv-space-0{flex-basis:0}
.fv-space-1,.fv-space-xs{flex-basis:4px}
.fv-space-2,.fv-space-sm{flex-basis:8px}
.fv-space-3{flex-basis:12px}
.fv-space-4,.fv-space-md{flex-basis:16px}
.fv-space-5{flex-basis:20px}
.fv-space-6,.fv-space-lg{flex-basis:24px}
.fv-space-8,.fv-space-xl{flex-basis:32px}
.fv-space-10{flex-basis:40px}
.fv-space-12{flex-basis:48px}
.fv-space-px{flex-basis:1px}
.fv-space-full{flex-basis:100%}
