@font-face {
  font-family: anova-light;
  font-style: normal;
  font-weight: 300;
  font-display: fallback;
  src: url("/styles/fonts/anova-light.woff2") format("woff2");
}

@font-face {
  font-family: anova-reg;
  font-style: normal;
  font-weight: 400;
  font-display: fallback;
  src: url("/styles/fonts/anova-reg.woff2") format("woff2");
}

@font-face {
  font-family: anova-bold;
  font-style: normal;
  font-weight: 700;
  font-display: fallback;
  src: url("/styles/fonts/anova-bold.woff2") format("woff2");
}



:root {
  /* font tokens */
  --font-primary-1: "anova-light", Arial, Helvetica, sans-serif;
  --font-primary-2: "anova-reg", Arial, Helvetica, sans-serif;
  --font-primary-3: "anova-bold", Arial, Helvetica, sans-serif;

  /* grid */
  --grid-container-width: 83.4%;
  --grid-column-width: calc(var(--grid-container-width) / 12);
  --grid-gutter-width: 8.3%;

  /* -----------------------------------------------------------------------
     SAS design-token layer (the finalized palette from the design team's
     styles/new-styles.css). This is the ONLY color palette — the legacy
     piecemeal --color-{gray|green|teal|blue|…}-NNN scales were removed; their
     few live usages were remapped to the brand tokens below.

     There is ONE scale per concern, and blocks consume only the semantic layer:

       color        --color-primary-N / --color-secondary-N / --color-neutral-N
       type size    --text-2xs … --text-7xl (fluid clamp)
       line height  --leading-tight … --leading-relaxed
       spacing      --spacing-0 … --spacing-6xl
       radius       --border-radius-s / -m / -l / -pill / -circle
       shadow       --shadow-s / -m / -l
       border       --border-s / -m / -l (+ --border-width-s / -m / -l)

     Removed in the EDGE-362 token consolidation — do NOT reintroduce:
       - the light/dark color schemes (`color-scheme`, `.light-scheme`,
         `.dark-scheme`, `light-dark()`); the site is light-only
       - the aliasing named-color layer (--color-text, --color-link,
         --color-brand, --color-accent, --color-background, --color-shaded,
         --color-charcoal, --color-light, --color-light-base, --color-dark,
         --color-dark-base) — use the semantic --color-… tokens directly
       - the fixed --heading-font-size-… and --body-font-size-… scales, plus
         --heading-line-height / --body-line-height — use --text-… / --leading-…

     The full spacing scale is the design team's. The legacy fixed-px
     --spacing-l/xl/xxl were migrated to it: every consumer was re-pointed to the
     fluid step whose max matches the old fixed value (l 24px→xl, xl 32px→2xl,
     xxl 48px→3xl), so desktop spacing is unchanged while gaining fluid scaling.
     ----------------------------------------------------------------------- */

  /* SAS base color tokens — primary */
  --blue-light:     #c4defd;
  --blue-med:       #4398f9;
  --sas-blue:       #0766d1;
  --blue-deep:      #032954;

  /* neutral group (legacy gray equivalents noted) */
  --white:          #fff;
  --linen:          #f8f9fb; /* legacy gray10 */
  --fog:            #e9edf1; /* legacy gray9 */
  --stone:          #ccd3dd; /* legacy gray6 */
  --smoke:          #b1bac8; /* legacy gray2 */
  --sas-gray:       #7e889a; /* legacy gray */
  --charcoal:       #454e5d; /* legacy gray3 */
  --black:          #000;

  /* secondary group */
  --teal-light:     #79e8f2;
  --teal:           #3adbe6;
  --teal-deep:      #06c1cc;
  --yellow-light:   #ffdf73;
  --yellow:         #fc3;
  --yellow-deep:    #d9a30b;
  --red-light:      #f99;
  --red:            #f24949;
  --red-deep:       #cc2d2d;
  --green-light:    #79f2af;
  --green:          #36d982;
  --green-deep:     #29b869;
  --pink-light:     #ff66b2;
  --pink:           #db127d;
  --pink-deep:      #850d4a;

  /* SAS named color tokens (semantic map) */
  --color-primary-1:    var(--sas-blue);
  --color-primary-2:    var(--blue-deep);
  --color-primary-3:    var(--blue-light);
  --color-primary-4:    var(--blue-med);
  --color-secondary-1:  var(--teal-light);
  --color-secondary-2:  var(--teal);
  --color-secondary-3:  var(--teal-deep);
  --color-secondary-4:  var(--yellow-light);
  --color-secondary-5:  var(--yellow);
  --color-secondary-6:  var(--yellow-deep);
  --color-secondary-7:  var(--red-light);
  --color-secondary-8:  var(--red);
  --color-secondary-9:  var(--red-deep);
  --color-secondary-10: var(--green-light);
  --color-secondary-11: var(--green);
  --color-secondary-12: var(--green-deep);
  --color-secondary-13: var(--pink-light);
  --color-secondary-14: var(--pink);
  --color-secondary-15: var(--pink-deep);
  --color-neutral-1:    var(--black);
  --color-neutral-2:    var(--white);
  --color-neutral-3:    var(--linen);
  --color-neutral-4:    var(--fog);
  --color-neutral-5:    var(--stone);
  --color-neutral-6:    var(--smoke);
  --color-neutral-7:    var(--sas-gray);
  --color-neutral-8:    var(--charcoal);

  /* fluid type scale (min → max) */
  --text-2xs: clamp(0.625rem, 0.595rem + 0.10vw, 0.75rem); /* 10 → 12 */
  --text-xs: clamp(0.75rem, 0.72rem + 0.10vw, 0.875rem);   /* 12 → 14 */
  --text-s: clamp(0.875rem, 0.85rem + 0.10vw, 1rem);       /* 14 → 16 */
  --text-m: clamp(1rem, 0.97rem + 0.15vw, 1.125rem);       /* 16 → 18 */
  --text-l: clamp(1.25rem, 1.15rem + 0.30vw, 1.5rem);      /* 20 → 24 */
  --text-xl: clamp(1.5rem, 1.35rem + 0.50vw, 2rem);        /* 24 → 32 */
  --text-2xl: clamp(2rem, 1.8rem + 0.80vw, 2.5rem);        /* 32 → 40 */
  --text-3xl: clamp(2.5rem, 2.2rem + 1.00vw, 3rem);        /* 40 → 48 */
  --text-4xl: clamp(3rem, 2.7rem + 1.30vw, 4rem);          /* 48 → 64 */
  --text-5xl: clamp(3.5rem, 3.1rem + 1.60vw, 4.5rem);      /* 56 → 72 */
  --text-6xl: clamp(4rem, 3.5rem + 2.00vw, 5rem);          /* 64 → 80 */
  --text-7xl: clamp(4.5rem, 4rem + 2.50vw, 6rem);          /* 72 → 96 */

  /* line height — the four steps the blocks had converged on by hand
     (1.15 was --heading-line-height, 1.6 was --body-line-height) */
  --leading-tight: 1.15;    /* headings; absorbs the hand-written 1.1/1.2 */
  --leading-snug: 1.3;      /* card titles, tight multi-line labels */
  --leading-normal: 1.4;    /* card copy, UI text; absorbs 1.35/1.45/1.5 */
  --leading-relaxed: 1.6;   /* body copy — the site default */

  /* larger fluid spacing steps (small --spacing-0…xl defined above) */
  --spacing-0: 0;
  --spacing-xs: 0.25rem;                                    /* 4px */
  --spacing-s: 0.5rem;                                      /* 8px */
  --spacing-m: 0.75rem;                                     /* 12px */
  --spacing-l: 1rem;                                        /* 16px */
  --spacing-xl: clamp(1.25rem, 1.1rem + 0.5vw, 1.5rem);     /* 20 → 24px */
  --spacing-2xl: clamp(1.75rem, 1.5rem + 0.8vw, 2rem);      /* 28 → 32 */
  --spacing-3xl: clamp(2.5rem, 2.1rem + 1.2vw, 3rem);       /* 40 → 48 */
  --spacing-4xl: clamp(3rem, 2.5rem + 1.8vw, 4rem);         /* 48 → 64 */
  --spacing-5xl: clamp(4rem, 3.4rem + 2vw, 5rem);           /* 64 → 80 */
  --spacing-6xl: clamp(5rem, 4.3rem + 2.5vw, 6rem);         /* 80 → 96 */

  /* border radius — s/m/l absorb the hand-written 2/4/5px, 8/10px and 12/20px */
  --border-radius-s: 4px;
  --border-radius-m: 8px;
  --border-radius-l: 12px;
  --border-radius-pill: 999px;
  --border-radius-circle: 50%;

  /* elevation — one scale for every card / popover / floating control */
  --shadow-s: 0 1px 6px color-mix(in srgb, var(--color-neutral-1) 12%, transparent);
  --shadow-m: 0 2px 8px color-mix(in srgb, var(--color-neutral-1) 16%, transparent);
  --shadow-l: 0 8px 24px color-mix(in srgb, var(--color-neutral-1) 20%, transparent);

  /* motion — one curve and three durations for every state change on the site.
     Absorbs the hand-written 0.15/0.2/0.25/0.3/0.4/0.5s and the ease /
     ease-in-out / ease-out mixture the blocks had drifted into — 63 declarations
     across 19 sheets, in 27 distinct duration+easing combinations, no two blocks
     agreeing on a hover speed.

     The CURVE is one value on purpose: ease-in-out for everything, so a hover,
     a fade and a slide all decelerate the same way and the site reads as one
     surface. The DURATION is three, because they are not the same kind of
     motion — see each step. Reach for `base` unless you can say why not.

     `--card-transition` in styles/card-system.css maps `base`; a component alias like
     that is fine, a fourth duration is not. */
  --transition-fast: 0.15s ease-in-out;  /* micro-interactions: a small control's
                                            own hover / focus, an icon recolour */
  --transition-base: 0.25s ease-in-out;  /* the default: card hovers, shadows,
                                            links, backgrounds */
  --transition-slow: 0.5s ease-in-out;   /* structural motion the eye follows:
                                            a carousel track, an image filter */

  /* border width */
  --border-width-s: 1px;
  --border-width-m: 2px;
  --border-width-l: 3px;

  /* composed borders — the three that actually recur across the blocks */
  --border-s: var(--border-width-s) solid var(--color-neutral-5);  /* hairline / divider */
  --border-m: var(--border-width-m) solid var(--color-primary-1);  /* brand emphasis */
  --border-l: var(--border-width-l) solid var(--color-primary-1);  /* heavy brand */

  /* ── Form design tokens ─────────────────────────────────────────────────────
     The single source of truth for how every SAS.com form presents and behaves,
     per the forms requirements of 2026-09-08 (§9 Design System Tokens, §10
     Scalability): a form's look is changed HERE, once, and no form
     implementation is edited.

     These are a COMPONENT layer, not an addition to the design-owned palette or
     spacing scales — every value below either resolves to an existing
     --color-… / --spacing-… / --text-… / --border-… / --shadow-… /
     --transition-… token, or is geometry belonging to the control itself (a
     control's pixel height, a shake's travel) that no scale on this site names.
     Nothing here mints a new colour or a new spacing step.

     ⚠ THE NAMES ARE CHOSEN NOT TO COLLIDE WITH THE VENDORED FORMS ENGINE, and
     that constraint is load-bearing rather than stylistic. blocks/aem-form/form.css
     is upstream's stylesheet and declares its OWN `--form-…` block at `:root` —
     --form-label-font-size, --form-input-font-size, --form-error-color,
     --form-input-padding, --form-field-gap, --form-button-…, and ~50 more. It is
     imported by aem-form.css and therefore loads AFTER this file, so any name
     shared with it would be silently overwritten by upstream's value the moment
     a form appeared on the page. Every token below deliberately differs from the
     engine's spelling (ours `--form-label-size`, theirs `--form-label-font-size`),
     and `main .form` in blocks/aem-form/aem-form.css is where the engine's
     variables are mapped onto these.

     So: before adding a token here, check it is not in that `:root` block — and
     after a re-sync from ../sas-forms, check upstream has not claimed one of
     these names. A collision does not error; it just stops the token working. */

  /* sizing — the control geometry. Literals because no scale on this site names
     a form control's height; 42px and 100px are the engine's own values, stated
     here so they can be changed from one place rather than overridden. */
  --form-max-width: 760px;
  --form-input-height: 42px;
  --form-textarea-min-height: 100px;
  --form-control-size: 16px;         /* the checkbox / radio box */

  /* field spacing. --form-label-gap is 8px PER THE BRIEF (§2 "8px spacing
     between label and associated input"); it supersedes the 5px the Figma
     global-form frame measured — see the field-pitch note in aem-form.css. */
  --form-label-gap: var(--spacing-s);
  --form-field-row-gap: var(--spacing-xl);
  --form-field-column-gap: var(--spacing-3xl);
  --form-input-padding-block: var(--spacing-s);
  --form-input-padding-inline: var(--spacing-l);
  --form-action-gap: var(--spacing-l);   /* extra air above the submit row */

  /* typography. The form runs a step below body copy on purpose: a 10-field
     panel beside an article should not out-weigh it. */
  --form-font-family: var(--font-primary-1);
  --form-label-size: var(--text-xs);
  --form-label-weight: 400;
  --form-input-size: var(--text-s);
  --form-help-size: var(--text-xs);

  /* There is deliberately no form-button-size token — the button's type is the DESIGN
     SYSTEM's, not the form's.
     `.btn` in styles.css declares it, and blocks/aem-form/aem-form.css imports the
     vendored engine into a cascade layer so that declaration wins. A token here would
     advertise control this layer does not have. */

  /* border + radius */
  --form-border-width: var(--border-width-s);
  --form-border-color: var(--color-neutral-7);
  --form-border-radius: var(--border-radius-s);
  --form-control-border-color: var(--color-neutral-8);  /* checkbox / radio: a
     16px box needs the darker edge to register at all, where a 42px field would
     look boxed-in with it. Hence its own token rather than the field colour. */

  /* colors */
  --form-ink: var(--color-neutral-1);
  --form-label-ink: var(--color-neutral-1);
  --form-help-ink: var(--color-neutral-8);
  --form-placeholder-ink: var(--color-neutral-7);
  --form-surface: var(--color-neutral-2);
  --form-disabled-surface: var(--color-neutral-4);
  --form-accent: var(--color-primary-1);

  /* focus state (§5). The scale is the brief's 108%; the elevation and the
     brand border are the other two halves of the same state. */
  --form-focus-scale: 1.08;
  --form-focus-border-color: var(--color-primary-1);
  --form-focus-border-width: var(--border-width-m);
  --form-elevation-rest: none;
  --form-elevation-focus: var(--shadow-m);
  --form-focus-ring: var(--border-width-m) solid var(--color-primary-1);
  --form-focus-ring-offset: var(--border-width-m);

  /* validation state (§6). red-deep rather than red so the asterisk, the error
     note and the recoloured label all clear AA against white. */
  --form-error-ink: var(--color-secondary-9);
  --form-error-border-color: var(--color-secondary-9);
  --form-error-surface: var(--color-neutral-3);

  /* animation values (§9). --form-transition is the site's `fast` step: a
     field's own focus is a micro-interaction by that token block's own
     description. The shake is an ANIMATION, not a transition, so it names its
     own duration rather than reaching for a fourth --transition-… step; 0.4s is
     four direction changes at --form-shake-distance, which reads as a nudge
     rather than a wobble. */
  --form-transition: var(--transition-fast);
  --form-shake-distance: 3px;
  --form-shake-duration: 0.4s;

  /* dropdown (§4). The chevron is a data URI rather than /icons/…: an
     externally-referenced SVG in `background-image` cannot take a colour from
     this document, and a <select> is a replaced element with no pseudo-element
     to hang a mask on — the same two reasons the form's checkbox tick is inline.

     ⚠ The stroke is the ONE place in this block that restates a palette hex rather
     than reading a token: #454e5d is --charcoal, and a data URI cannot substitute a
     custom property (the URL is parsed as an opaque string). Recolour by editing the
     stroke, and keep it in step with --charcoal if design moves that value. */
  --form-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23454e5d' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --form-select-chevron-size: 12px;
  --form-select-chevron-inset: var(--spacing-l);

  /* misc */
  --header-height: 64px;
  --breadcrumb-height: 24px;

}

@media (width >= 900px) {
  :root {
    --header-height: 70px;
  }
}

/* Keeps a fragment target clear of whatever is fixed or stuck above it: the
   header always, and the sticky title-shelf on the pages that carry one, which
   declares --title-shelf-height at page scope for this calc to read (see
   blocks/title-shelf/title-shelf.css). Unset elsewhere, hence the 0px fallback.
   Applies to every scroll-into-view, so an authored `#guide` — see the
   section-metadata `anchor-id` key — and a heading link land the same way. */
html {
  scroll-padding-top: calc(var(--header-height) + var(--title-shelf-height, 0px) + 1rem);

  /* Fragment navigation eases to the target instead of jumping to it, so a
     `#guide` button and a heading link both read as movement down the page
     rather than as a new page.

     `scroll-behavior` is NOT inherited, so this reaches only the ROOT scroller:
     an inner scroll container — a modal body, a tab strip — keeps its own instant
     behaviour without having to opt out. The JS that already asks for smooth
     explicitly (tabs.js, aem-form) is unaffected either way, since the
     scrollIntoView option beats the property. */
  scroll-behavior: smooth;
}

/* Motion is the thing being turned off here, not an animation's duration: a
   reader who asks for less of it still has to ARRIVE at the anchor, so the jump
   comes back rather than the scroll being dropped. Written as an override of the
   rule above, the way accordion.css and tabs.css do it, rather than gating that
   rule behind `no-preference` — a browser that reports no preference at all then
   still gets the smooth scroll. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background-color: var(--color-neutral-2);
  color: var(--color-neutral-1);
  font-family: var(--font-primary-1);
  font-size: var(--text-m);
  line-height: var(--leading-relaxed);
  padding: var(--header-height) 0 0;

  &.session {
    /* only allow font loading if a session */
    font-family: var(--font-primary-1);
  }

  &.has-breadcrumb {
    margin: calc(var(--header-height) + var(--breadcrumb-height)) 0 0;
  }

  &.no-header {
    --header-height: 0;

    margin: 0;
  }
}

header {
  display: none;
  height: var(--header-height);
  position: fixed;
}

a {
  color: var(--color-primary-1);

  /* The underline is always PRESENT and merely transparent until hover, because
     `text-decoration-line` is NOT an animatable property — `none` -> `underline`
     is a discrete jump, so a `transition: text-decoration` has nothing to
     interpolate and the hover lands instantly. The COLOUR is animatable, so the
     line fades in instead.

     Longhands rather than the shorthand: `text-decoration: underline` would reset
     the colour back to currentcolor and show the line at rest.

     A real text-decoration rather than a pseudo-element underline, so it follows
     every line of a WRAPPED link — the same reason filter-list.css gives for
     using one.

     `fast`, not the `base` the token block nominates for links: base is the right
     speed for a link that MOVES or changes ground (a card lifting, a pill filling),
     where the eye follows the change. This is a hairline recolouring under a cursor
     already in motion — the token block's own description of `fast`. At base it
     reads as lag on a pointer sweeping a paragraph of links.

     `:focus-visible` alongside `:hover` so the affordance is not pointer-only.

     The offset is left `auto` deliberately. A raised `<sup>` — the registered mark
     in `SAS<sup>®</sup> Viya<sup>®</sup>`, which is how most product links in this
     content are written — makes the link's line box taller, but measured against a
     fixed reference edge that does NOT move the underline: Chromium derives an
     `auto` underline from the DECORATING BOX's font metrics, so a link with a ® in
     it and one without underline at exactly the same height. Pinning an offset here
     buys nothing and only moves every underline on the site. */
  text-decoration-line: underline;
  text-decoration-color: transparent;
  transition: text-decoration-color var(--transition-fast);

  &:hover,
  &:focus-visible {
    text-decoration-color: currentcolor;
  }

  /* A link whose ENTIRE label is a <sup> or <sub> — `<a><sub>privacy@sas.com</sub></a>`,
     which is how the trust-center page authors its small print. A decoration is drawn
     by its DECORATING BOX, so an underline declared on the `a` lands on the A's
     baseline while the label's glyphs sit lowered (sub) or raised (sup): the line
     runs THROUGH the text instead of under it, surviving only as fragments between
     the letters. Hand the decoration to the sup/sub, which sits on the baseline the
     glyphs actually use.

     The `link-script-label` marker is set in scripts.js, not matched here, because
     no selector can express it — see the note there. */
  &.link-script-label {
    text-decoration-line: none;

    > :is(sup, sub) {
      text-decoration-line: underline;
      text-decoration-color: transparent;
      transition: text-decoration-color var(--transition-fast);
    }

    &:hover > :is(sup, sub),
    &:focus-visible > :is(sup, sub) {
      text-decoration-color: currentcolor;
    }
  }
}

/* ── Buttons ──────────────────────────────────────────────────────────────────
   `:is(a, button)`, not `a`. These rules used to live INSIDE the `a { }` block
   above, which meant the whole button vocabulary styled anchors only and a
   `<button class="btn btn-accent">` rendered as an unstyled UA button — no
   colour, no arrow, no hover.

   That mattered the moment a button had to BE a button. The leadership toolbox's
   "Abstract bios" control opens a dialog, and a control that opens a dialog is a
   `<button>`, not a link: a link navigates, a button acts. `modal.js` builds it
   as one, correctly. So the choice was to widen these selectors or to break the
   semantics to get the look — emit an `<a href="#…">` that does not navigate and
   fake the rest with `role="button"` and key handlers. Widening is the cheaper
   and the more accessible answer.

   Only the BUTTON subtree moved. The `a { }` block keeps its link rules — the
   brand colour and the fade-in underline — because those are wrong on a button:
   widening the outer selector instead would paint every unstyled `<button>` on
   the site brand blue.

   Blast radius today is nil: nothing in this repo put `.btn` on a non-anchor
   before this (checked across ak.js, hero, webinar and card-cta, which all
   decorate links), so no existing element starts matching. It is only new
   capability.
   ------------------------------------------------------------------------- */
:is(a, button) {
  &.btn {
    /* A button carries the SITE's body font, not whatever font the copy around
       it happens to be set in — the same values `body` declares, so an ordinary
       button is pixel-identical to what it rendered before this was written.

       It has to be declared, because a pill in ordinary default content is
       `<p><a class="btn">`, and Section Metadata `body-font-style = l` sizes
       that `<p>`; with nothing of its own the button INHERITED it and rendered
       22.72px against every other button on the site at 17.68px. One block
       declares a font on a `.btn` — blocks/side-nav sizes its rail CTA one step
       down at (0,3,0) — and nothing else does (checked across every block), so
       this overrides nothing and only stops the inheritance.

       section-metadata.css's own comment on those rows already asserts this is
       true — "headings, `strong` and `.btn` all declare their own family and
       size, so only the copy that had none follows". It was true of the other
       two and not of this one; the comment is now correct as written.

       Here rather than as an exemption in section-metadata.css because the leak
       is not that key's: any context that sizes the copy a button sits in would
       have moved it. One declaration covers all of them.

       DECLARED BELOW `font: inherit`, NOT ABOVE IT — see the note there. */
    display: inline-flex;
    text-decoration: none;
    border: var(--border-width-s) solid var(--color-primary-1);

    /* What an `<a>` gave for free and a `<button>` does not: a button carries the
       UA's own small system font and, in some browsers, an arrow cursor. Both are
       no-ops on an anchor, so they cost the existing consumers nothing.

       ORDER IS LOAD-BEARING, and the two lines under this one must stay under it.
       `font` is a SHORTHAND: it resets family, size, weight, style, line-height
       and variant, so with the family/size declared above it they were silently
       thrown away and every `.btn` went back to inheriting its size from the copy
       around it — the exact leak they exist to stop, and now on `<button>` too.
       Both intents survive in this order: the shorthand clears the UA font and
       takes weight/line-height from the context (which is what makes a `<button>`
       match an `<a>`), then the two longhands pin the family and size to the
       site's own rather than the surrounding copy's. */
    font: inherit;
    font-family: var(--font-primary-1);
    font-size: var(--text-m);
    cursor: pointer;
    padding: var(--spacing-l) var(--spacing-xl);
    box-sizing: border-box;
    border-radius: var(--border-radius-pill);
    align-items: center;
    gap: var(--spacing-s);
    transition: transform var(--transition-base);

    &:hover, &:focus-visible {
      transform: scale(1.1);
    }



    &.btn-outline {
      background: transparent;
    }
  }

  /* Text button — a plain brand-blue link with the site's arrow after it.
     Replaces the old accent pill (dark navy fill, 2px navy border).

     Authored as a bold+italic link (`***Get pricing by credential***`), which
     ak.js maps to `btn-accent`. ak.js replaces the em/strong wrapper with the
     link itself, so the label renders at regular weight; the emphasis is
     authoring syntax, not a visual instruction.

     THE CLASS NAME IS THE AUTHOR KIT'S, THE LOOK IS OURS. This used to be a
     one-line patch in scripts/ak.js making it emit `btn-text` instead — which
     worked, and silently un-worked on the next AK sync, needing a comment there
     begging the next person to re-apply it. ak.js is a synced upstream file:
     the repo already keeps the aem-form helpers out of it in scripts/sas.js for
     exactly this reason. A restyle belongs in our stylesheet, where a sync
     cannot touch it.

     `btn-text` is kept as an alias — it is the name this repo, its docs and its
     blocks say, and it costs one selector. Nothing emits it today, so if you are
     reading the DOM you will see `btn-accent`. */
  &.btn-accent,
  &.btn-text {
    /* Undo the .btn pill — this is text, not a discrete control. The
       inline-flex / align-items / gap from .btn are deliberately kept: they are
       exactly what sits the arrow beside the label. */
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    color: var(--color-primary-1);

    /* The site's single arrow icon, painted as a MASK so it takes the label's
       colour through currentcolor rather than the file's own #0766D1 fill — a
       background-image would look identical today but would freeze the colour
       and stop tracking the token. Same icon and same 17x18 drawn size as the
       card grids' arrow (styles/card-system.css), so the site draws one arrow.
       `align-items: center` on .btn centres it against the label's glyphs. */
    &::after {
      content: '';
      flex: 0 0 auto;
      width: 17px;
      height: 18px;
      background-color: currentcolor;
      mask: url("/icons/arrow-right.svg") no-repeat center / contain;
    }

    /* 5%, against the pill's 10%: this sits in the reading flow as text, so it
       wants a lighter touch than a button does. */
    &:hover, &:focus-visible {
      transform: scale(1.05);
    }

    /* `btn-outline` (authored as an underline) has no fill or border to outline
       here, so it collapses to the same treatment rather than doing nothing
       visible at a different colour. */
    &.btn-outline {
      color: var(--color-primary-1);
      background: transparent;
    }
  }

  &.btn-primary {
    color: var(--color-neutral-2);
    background-color: var(--color-primary-1);

    &.btn-outline {
      color: var(--color-primary-1);
      background: transparent;
    }
  }

  &.btn-secondary {
    color: var(--color-primary-1);
    background-color: var(--color-neutral-2);
    border: var(--border-width-s) solid var(--color-primary-1);

    &.btn-outline {
      color: var(--color-neutral-7);
    }
  }

  &.btn-negative {
    color: var(--color-neutral-2);
    background-color: var(--color-secondary-9);
    border: var(--border-width-m) solid var(--color-secondary-9);

    &.btn-outline {
      color: var(--color-secondary-9);
    }
  }
}

/* ── Button groups ────────────────────────────────────────────────────────────
   `**[Get pricing](…)** **[Compare plans](…)**` — a paragraph whose every child is
   a link run. `decorateButton` in scripts/ak.js marks it `btn-group`; until now
   NOTHING styled that class, so the only thing between two buttons was the
   collapsed whitespace text node from the source: about 4px, with a filled pill's
   edge landing that far from its neighbour's label.

   Per meeting with Eric, 2026-09-02.

   MARGIN, not a flex `gap`, and the choice is load-bearing. Making the paragraph a
   flex container would give exact gaps but take the buttons out of inline flow —
   and `text-align: center`, which is how every centring context on this site
   centres a button row (a section `style = center`, `Columns (center)`, a centred
   hero), stops reaching them. Restoring that would mean `justify-content` rules
   enumerating every one of those contexts: a list that goes stale silently. Inline
   flow keeps centring, wrapping and alignment working with no list to maintain.

   `margin-inline-END` on all but the last, rather than `-start` on all but the
   first, so a group that WRAPS starts its second line flush instead of indented by
   the gap. The trailing margin at the end of a wrapped line is invisible.

   Two known imprecisions, both accepted: the collapsed word space still sits in
   every gap, so the rendered figure is the token plus ~4px — an 8px base renders
   nearer 12px, and at these steps that is a third of the value rather than the
   quarter it was, though it is the same ~4px in EVERY pairing so it never disturbs
   the DIFFERENCE between the two gaps below; and a wrapped CENTRED group is
   off-centre by half its trailing margin.
   ------------------------------------------------------------------------- */

.btn-group > .btn:not(:last-child) {
  margin-inline-end: var(--spacing-s);
}

/* A pill next to a text button, in either order, adds `--spacing-l` — so the base
   8px becomes 8 + 16 = 24px.

   A pill carries its inline padding INSIDE its fill, so two pills sit their labels
   `20–24 + gap + 20–24` apart. `btn-accent` zeroes that padding, so a pill beside
   one sat its labels only `20–24 + gap` apart and the bare label read as crowded
   against the fill. The addition gives most of it back.

   THE TWO STEPS ARE TUNED SEPARATELY, and that is why this is stated as "the base
   plus `--spacing-l`" rather than as "one step wider". They have moved
   independently: `--spacing-l`/`--spacing-xl` at first, then both down twice to
   `--spacing-s`/`--spacing-m`, then this term alone back up. Any phrasing that
   describes the pair as N steps apart goes stale the next time one of them moves
   on its own.

   NOT an exact compensation, deliberately. Handing back the pill's whole inline
   padding (`--spacing-xl`, the token `.btn` sets it from) would equalise the
   label-to-label distance precisely; it reads too loose. As it stands a matched pair
   sits its labels 48–56px apart and a mixed pair 44–48px, i.e. 4–8px short of equal.

   So the RELATIONSHIP is the rule here and the arithmetic is not. Retune by moving
   either step on its own, never by re-deriving one from the pill's padding: that
   derivation was true only at the very first pair of values and it is exactly what
   someone checking the numbers will reach for. Note 8 + 16 lands on 24px, which IS
   the pill's inline padding at desktop — a coincidence of the current steps, not a
   derivation, and it will stop being true at the next tweak or below 1440.

   A "pill" is any `.btn` that is not one of the two text-button names, so a bare
   `.btn`, `btn-primary`, `btn-secondary`, `btn-negative` and a pill-with-`btn-outline`
   are all included without naming them — and a variant added later is a pill by
   default, which is the safe way round.

   At (0,4,0) against the base rule's (0,3,0), and `:has(+ …)` guarantees a next
   sibling, so this can never leave a trailing margin on the last button. */
.btn-group > .btn:not(.btn-accent, .btn-text):has(+ :is(.btn-accent, .btn-text)),
.btn-group > :is(.btn-accent, .btn-text):has(+ .btn:not(.btn-accent, .btn-text)) {
  margin-inline-end: calc(var(--spacing-s) + var(--spacing-l));
}

/* Both gaps above assume the group is in INLINE FLOW — that is the whole reason they
   are margins rather than a flex `gap` (see the note above). A block that takes the
   group OUT of inline flow therefore has to hand the margin back, because an inline
   margin on a flex/grid ITEM no longer sits between two buttons: under
   `align-items: stretch` it SHRINKS the item it is set on, by the width of the gap.

   The one such block today is the modal's dialog content
   (`.modal-content .btn-group` in blocks/modal/modal.css), which stacks an
   accept/decline pair into a stretch column precisely so the two buttons share an
   edge. Left alone, the non-last button rendered 8px narrower than its neighbour in a
   matched pair and 24px narrower in a mixed one — measured 568px against 592px at
   1440, i.e. the ragged edge that rule exists to prevent.

   The exception lives HERE, next to the assumption it carves out, rather than in
   modal.css: these two rules own the inline-flow premise, so a block that breaks it is
   this section's business to answer, and one place lists every context that does.

   At (0,5,0) it beats the (0,4,0) pairing rule above outright, so it does not depend on
   stylesheet load order — block CSS happens to load after this file, but a reset that
   is only correct because of that would be one refactor away from silently failing.
   `:not(:last-child)` rather than a blanket zero, so it answers exactly the two rules
   above and cannot swallow a margin something else sets on the last button. */
.modal-dialog .modal-content .btn-group > .btn:not(:last-child) {
  margin-inline-end: 0;
}

/* sections */

main .section:has(> .block-content > .hero),
main .section:has(> .block-content > .full-width-banner),
main .section:has(> .block-content > .alert) {
  padding: 0;
}

/* `columns (image-cover)` zeroes its section's padding too — but ONLY when every
   columns block in the section is flush.

   The reset exists because an `image-cover` block runs its media to all four of
   its own edges, so the section's vertical padding would reopen the gap above
   and below a Z-pattern the variant just closed. That holds for a section which
   IS that Z-pattern. It is wrong for a MIXED one: `:has()` matches on a single
   flush block, so one of them stripped the padding from everything else in the
   section — measured on /en/drafts/chase/company-information, a section of
   three `image-cover` blocks and three painted `bg-*` panels, where the last
   panel's bottom (3374) was the section's bottom (3374) and it butted straight
   into the linen band below with no gap at all.

   The exclusion names `.columns` specifically rather than any other block. The
   section's own `section-metadata` is a block div that removes itself at the end
   of its init, and `:has()` is live — a blanket "any other block" test would
   match it for that window and flicker the padding on and then off. Scoping to
   columns cannot see it.

   A mixed section now keeps its padding, which is the right answer: the flush
   treatment is about the BLOCK's edges, and a Z-pattern sitting among painted
   panels is content inside a section like any other. */
main .section:has(> .block-content > .columns.image-cover):not(
    :has(> .block-content > .columns:not(.image-cover))
  ) {
  padding: 0;
}

main.section {
  padding: 0;
}

/* The section's own top/bottom padding, and the only place it is set — so the
   two edges match. It was `var(--spacing-4xl) var(--spacing-2xl)`: `padding-block`
   is a start/end shorthand, so that was a 64px top against a 32px bottom, and a
   section read as sitting low in its own space. `--spacing-4xl` on both edges
   keeps the page's first TOP edge exactly where it was and raises the bottom to
   match it, so no section starts higher than it used to; the cost is that the gap
   BETWEEN two sections grows from 96px (32 + 64) to 128px (64 + 64).

   Expressed as a var() FALLBACK so Section Metadata `spacing = <step>` can win
   by simply setting the property. It could not override a padding declaration:
   `:has()` contributes its argument's specificity, making this selector (0,2,1)
   against `.section.spacing-2xl`'s (0,2,0), so an authored `spacing` row lost the
   block axis outright and reached only the inner `.default-content` margin in
   section-metadata.css — visibly doing something, but not the thing it names.

   The default lives HERE rather than in section-metadata.css because that
   stylesheet is loaded lazily (`loadStyle` in section-metadata.js, and via
   loadBlock otherwise), so a page authoring no Section Metadata anywhere would
   otherwise have no section padding at all.

   A `main .section { padding-block: 0 }` reset used to follow this rule. It was
   dead on arrival — (0,1,1) against (0,2,1), and later source order does not
   rescue a weaker selector — so it is gone rather than left implying sections
   start at zero. */
main .section:has(> .block-content),
main .section:has(> .default-content){
  padding-block: var(--top-bottom-spacing, var(--spacing-4xl));
}

.section {
  display: block;

  > .default-content {
    max-width: var(--grid-container-width);
    margin: 0 auto;
  }
}

.section.grey {
  background-color: var(--color-neutral-3);

  /* Sets the PROPERTY, not `padding` — a painted section wants its inset
     whatever the global rhythm is, and the `padding: var(--spacing-3xl) 0` this
     replaces was silently overridden on the block axis by the (0,2,1) rule
     above. At (0,2,0) it ties with `.section.spacing-2xl`, and section-metadata.css
     loads later, so an authored `spacing` row still wins. */
  --top-bottom-spacing: var(--spacing-3xl);
}

/* Legal disclaimer / fine print at the foot of an article (customer stories).
   --text-2xs, the smallest step on the scale (10 -> 12px): this is the one place
   on the site that wants to read as smaller than a caption or a field label,
   both of which sit at --text-xs. */

.section.disclaimer p {
  margin: 0;
  color: var(--color-neutral-8);
  font-size: var(--text-2xs);
  line-height: var(--leading-normal);
}

/* A lone image in its own paragraph auto-sizes to its container width —
   regardless of page — so authoring one at, say, 1500x844 in a narrow column
   never overflows it. Unscoped: this is a generic, always-sane default, not
   the article-only behavior below. */
.default-content p:has(> picture) img {
  width: 100%;
  height: auto;
  display: block;
}

/* Body images in article content — alternating float, pulling body copy up
   beside them. JS in social-sidebar.js adds .img-left to every second image
   paragraph. Default (no override class) floats right.

   Scoped to the customer-story article body — the section social-sidebar.js
   marks `has-social-sidebar` and every section after it (same sibling
   combinator social-sidebar.css already uses to extend that section's grid
   down the rest of the article) — NOT every `.default-content` site-wide. A
   lone image in an ordinary content page's default-content (no social sidebar
   anywhere before it) is plain authoring, not an article body illustration,
   and should stack in flow rather than float and pull the following
   paragraph up beside it. */
:is(.section.has-social-sidebar, .section.has-social-sidebar ~ .section) .default-content p:has(> picture) {
  float: right;
  clear: right;
  display: block;
  max-width: 42%;
  margin: 0.25rem 0 1.5rem 2rem;
  line-height: 0;
}

:is(.section.has-social-sidebar, .section.has-social-sidebar ~ .section) .default-content p:has(> picture).img-left {
  float: left;
  clear: left;
  margin: 0.25rem 2rem 1.5rem 0;
}

@media (width <= 768px) {
  :is(.section.has-social-sidebar, .section.has-social-sidebar ~ .section) .default-content p:has(> picture),
  :is(.section.has-social-sidebar, .section.has-social-sidebar ~ .section) .default-content p:has(> picture).img-left {
    float: none;
    clear: both;
    max-width: 100%;
    margin: 1.5rem 0;
    line-height: normal;
  }
}

main {
  ul,
  ol {
    padding-inline-start: 24px;

    /* Reduce nested lists even further */
    ul,
    ol {
      padding-inline-start: 12px;
    }
  }

  /* SAS blue bullet points on unordered lists (text stays default color). */
  ul > li::marker {
    color: var(--color-primary-1);
  }
}

button {
  cursor: pointer;
}

li {
  margin-block: 1em;
}

h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-primary-1);
  font-weight: 400;
  line-height: var(--leading-tight);
}

h1 { font-size: var(--text-3xl); font-family: var(--font-primary-2); font-weight: 400; line-height: var(--leading-tight)} 
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-l); }
h5 { font-size: var(--text-m); }
h6 { font-size: var(--text-s); }

strong, b {
  font-family: var(--font-primary-3);
}

input,
textarea,
select,
button {
  font: inherit;
}

img {
  width: 100%;
  height: auto;
}

svg {
  width: 20px;
  height: 20px;
}

/* @media (width >= 600px) {} */

/* @media (width >= 900px) {} */

/* @media (width >= 1200px) {} */

@media (width >= 1440px) {
  :root {
    --grid-container-width: 1200px;
  }
}

main > div,
.has-template,
div[data-status] {
  display: none;
}

aem-sidekick {
  opacity: 0;

  &[open="true"].is-ready {
    opacity: 1;
  }
}

/* Brightcove video styling */
.video-js .vjs-big-play-button {
    background-size: 15%;
}
