/* RomandaMedia theme base styles.

   Order matters. Tokens first so every layer below can reference them, then
   generic resets, then layout objects, then styled elements, then components,
   then utilities last so a helper class can win.

   Theme editor values arrive separately via theme-overrides.css, which
   base.html loads after this file.

   CACHE NOTE: HubSpot compiles this file into template_main.min.css and
   versions it from THIS file, not from the partials it includes. Editing only
   a partial leaves the compiled asset stale and the change never reaches the
   browser, with Design Manager showing the new source the whole time. Touching
   this file is what forces the rebuild. Last touched 2026-08-27 for the quiz
   input specificity fix.
*/

/* Tokens: the brand baseline, generated from brand-tokens/[client].json */
/* GENERATED by scripts/render_tokens.py. Do not edit by hand; edit the brand-tokens file and re-run. */
/* Brand: RomandaMedia  Source: functions/marketing/brand/releases/RomandaMedia-Brand-Book-v1.2.html */

:root {
  /* Palette */
  --palette-ink: #141019;
  --palette-charcoal: #3B3A45;
  --palette-slate: #5C5B66;
  --palette-mist: #E8E5F0;
  --palette-cloud: #F8F7FC;
  --palette-white: #FFFFFF;
  --palette-plum-900: #1A1433;
  --palette-indigo-700: #2A1F55;
  --palette-violet-600: #3F1D77;
  --palette-violet: #7338D2;
  --palette-violet-bright: #8B58E0;
  --palette-lavender: #C0A4FB;
  --palette-lavender-mist: #F1EBFF;
  --palette-sand: #C9B08A;
  --palette-bone: #F3ECDE;
  --palette-lime: #A7E130;
  --palette-pale-lime: #DAFF8E;
  --palette-moss: #5F8410;
  --palette-error: #B3261E;

  /* Semantic roles. Reference these, not the palette. */
  --color-primary: var(--palette-violet);
  --color-primary-deep: var(--palette-violet-600);
  --color-primary-bright: var(--palette-violet-bright);
  --color-secondary: var(--palette-plum-900);
  --color-accent: var(--palette-lime);
  --color-accent-soft: var(--palette-pale-lime);
  --color-accent-deep: var(--palette-moss);
  --color-text: var(--palette-ink);
  --color-text-muted: var(--palette-slate);
  --color-surface: var(--palette-white);
  --color-surface-alt: var(--palette-cloud);
  --color-surface-deep: var(--palette-plum-900);
  --color-surface-warm: var(--palette-bone);
  --color-border: var(--palette-mist);
  --color-on-primary: var(--palette-white);
  --color-on-accent: var(--palette-ink);
  --color-on-deep: var(--palette-white);
  --color-error: var(--palette-error);

  /* Gradients */
  --gradient-deep: linear-gradient(135deg,#1A1433 0%,#2A1F55 55%,#3F1D77 100%);

  /* Type */
  --font-head: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body: 'Lexend Deca', Arial, 'Helvetica Neue', Helvetica, sans-serif;
  --font-wordmark: 'Montserrat', Arial, sans-serif;

  /* Radii (theme decision, not a brand-book value) */
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  /* Layout (theme decision) */
  --layout-content-max: 1200px;
  --layout-content-narrow: 760px;
  --layout-gutter: 24px;
}

/* Generic: reset and normalize. No brand opinion lives here. */
*, *:before, *:after {
  box-sizing: border-box;
}

/* THE hidden ATTRIBUTE HAS TO WIN.

   The browser's own rule is `[hidden] { display: none }`, specificity 0,0,1.
   This theme sets `button { display: inline-block }` in the elements layer at
   the SAME specificity and later in the cascade, so it wins, and `hidden` stops
   working on every button in the theme. Setting `el.hidden = true` in JS then
   does nothing visible and there is no error to notice.

   Found 2026-08-27: the audit quiz's Back button stayed on screen at step one
   with hidden="" correctly set on the element.

   !important is right here rather than a specificity bump, because `hidden`
   means hidden and nothing in a component should be able to out-rank it. */
[hidden] { display: none !important; }
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */

/* Document
   ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */

html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/* Sections
   ========================================================================== */

/**
 * Remove the margin in all browsers.
 */

body {
  margin: 0;
}

/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/* Grouping content
   ========================================================================== */

/**
 * Add the correct box sizing in Firefox.
 */

hr {
  box-sizing: content-box;
  height: 0;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/* Text-level semantics
   ========================================================================== */

/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.
 */

abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}

/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */

b,
strong {
  font-weight: bolder;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */

code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}

/**
 * Add the correct font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/* Forms
   ========================================================================== */

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}

/**
 * Remove the inheritance of text transform in Edge and Firefox.
 * 1. Remove the inheritance of text transform in Firefox.
 */

button,
select { /* 1 */
  text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */

button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */

fieldset {
  padding: 0.35em 0.75em 0.625em;
}

/**
 * Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers.
 */

legend {
  padding: 0;
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */

progress {
  vertical-align: baseline;
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */

[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/* Interactive
   ========================================================================== */

/*
 * Add the correct display in Edge and Firefox.
 */

details {
  display: block;
}

/*
 * Add the correct display in all browsers.
 */

summary {
  display: list-item;
}

/* Objects: non-cosmetic layout patterns */
/* Layout objects. Structure only, no cosmetics. */

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

img, video, svg { max-width: 100%; height: auto; }

/* The standard centred column. Every section's inner wrapper. */
.content-wrapper {
  width: 100%;
  max-width: var(--layout-content-max);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--layout-gutter);
  padding-right: var(--layout-gutter);
}

.content-wrapper--narrow { max-width: var(--layout-content-narrow); }

/* Vertical rhythm between page sections. */
.section {
  padding-top: var(--layout-section-y, 80px);
  padding-bottom: var(--layout-section-y, 80px);
}

.section--tight { padding-top: 48px; padding-bottom: 48px; }
.section--alt { background-color: var(--color-surface-alt); }
.section--warm { background-color: var(--color-surface-warm); }
.section--deep { background: var(--gradient-deep); color: var(--color-on-deep); }

/* Auto-fitting card grid. min is the smallest a card may get before wrapping.

   THE min() IS LOAD-BEARING, do not simplify it to minmax(var(--grid-min), 1fr).

   A bare minmax() minimum is a floor the track will not go below EVEN WHEN THE
   CONTAINER IS NARROWER. At 375px the content wrapper is 343px wide, so a
   380px minimum produced 380px cards that ran 21px past the viewport: a real
   horizontal scrollbar, plus content that looked mis-centred because it sat
   flush left and overhung on the right. That is the "left has more padding
   than the right" report from mobile, 2026-08-27.

   min(var(--grid-min), 100%) clamps the floor to the container, so the track
   is 380px when there is room and full-width when there is not. */
.grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 260px), 100%), 1fr));
}

.grid--2 { --grid-min: 380px; }
.grid--4 { --grid-min: 200px; }

/* Two-column split for a hero or an image-beside-text row. */
.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--wide-left { grid-template-columns: 1.25fr 1fr; }
}

.stack > * + * { margin-top: var(--stack-gap, 1rem); }

/* Accessibility: the skip link target used by header.html. */
.screen-reader-text {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link:focus {
  position: fixed;
  top: 0.5rem; left: 0.5rem;
  z-index: 999;
  width: auto; height: auto;
  clip: auto;
  padding: 0.75em 1.25em;
  background: var(--color-surface);
  color: var(--color-text);
  border-radius: var(--radius-sm);
}
.content-wrapper {
  margin: 0 auto;
  padding: 0 1rem;
}

@media screen and (min-width: 1380px) {
  .content-wrapper {
    padding: 0;
  }
}

.dnd-section > .row-fluid {
  margin: 0 auto;
}

.dnd-section .dnd-column {
  padding: 0 1rem;
}

@media (max-width: 767px) {
  .dnd-section .dnd-column {
    padding: 0;
  }
}

/* Elements: bare HTML elements */
/* Type scale.

   Fraunces for headings, Lexend Deca for body, per Brand Book v1.2. Sizes use
   clamp() so the scale is fluid between the mobile breakpoint and the content
   max width, which avoids a separate set of media queries per heading level.
*/

html {
  font-size: 100%;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--color-text);
  background-color: var(--color-surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-head);
  color: var(--color-text);
  line-height: 1.12;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.25rem, 5.5vw, 3.75rem); font-weight: 800; letter-spacing: -0.02em; }
h2 { font-size: clamp(1.85rem, 4vw, 2.75rem); font-weight: 700; letter-spacing: -0.015em; }
h3 { font-size: clamp(1.45rem, 3vw, 1.95rem); font-weight: 700; }
h4 { font-size: clamp(1.2rem, 2.2vw, 1.4rem); font-weight: 600; }
h5 { font-size: 1.15rem; font-weight: 600; }
h6 { font-size: 1rem; font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  transition: color 0.15s ease;
}

a:hover,
a:focus { color: var(--color-primary-deep); }

/* The eyebrow above a heading. Lime is the signal colour and is used sparingly. */
.eyebrow {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-deep);
  margin: 0 0 0.75em;
}

.lead {
  font-size: 1.25rem;
  line-height: 1.55;
  color: var(--color-text-muted);
}

blockquote {
  margin: 1.5em 0;
  padding: 0 0 0 1.25em;
  border-left: 3px solid var(--color-accent);
  font-size: 1.15rem;
}

hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 2.5rem 0;
}

/* Dark sections invert the type colours without needing a second set of rules. */
.on-deep,
.on-deep h1, .on-deep h2, .on-deep h3, .on-deep h4, .on-deep h5, .on-deep h6 {
  color: var(--color-on-deep);
}

.on-deep .lead { color: var(--palette-lavender); }

/* The eyebrow's default is the deep moss green, which is legible on white and
   nearly invisible on the deep gradient. */
.on-deep .eyebrow { color: var(--color-accent-soft); }
/* Buttons are excluded: .on-deep a beats .button--accent on specificity
   (0,1,1 vs 0,1,0), which silently turned lime button text pale and
   unreadable. Caught on the Phase 1 render check. */
.on-deep a:not(.button) { color: var(--color-accent-soft); }
/* Buttons.

   Three variants: solid primary, lime accent, and outline. HubSpot's CTA and
   form submit elements are given the same treatment here so a form button
   never looks like a different design system.

   CONVENTION, and it is not optional. Any component rule that styles links by
   element must exclude buttons:

       .thing a:not(.button) { color: ... }

   `.thing a` scores 0,1,1 and `.button` scores 0,1,0, so without the :not() the
   component silently repaints button text. This has now bitten twice in one
   session: lime buttons on a dark hero went pale and unreadable, and the header
   CTA rendered ink-on-violet. Both published fine and both looked broken.
*/

.button,
button,
.hs-button,
input[type="submit"],
input[type="button"] {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  padding: 0.875em 1.75em;
  border: 1.5px solid transparent;
  border-radius: var(--button-radius, var(--radius-pill));
  background-color: var(--button-bg, var(--color-primary));
  color: var(--button-text, var(--color-on-primary));
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.button:hover,
button:hover,
.hs-button:hover,
input[type="submit"]:hover {
  background-color: var(--color-primary-bright);
  color: var(--color-on-primary);
  transform: translateY(-1px);
  box-shadow: 0 8px 24px rgba(115, 56, 210, 0.28);
}

.button:focus-visible,
button:focus-visible,
.hs-button:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

/* Lime. The signal colour, reserved for the single most important action on a
   page. Ink text on lime is the only accessible pairing; never white. */
.button--accent {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

.button--accent:hover {
  background-color: var(--palette-pale-lime);
  color: var(--color-on-accent);
  box-shadow: 0 8px 24px rgba(167, 225, 48, 0.35);
}

.button--outline {
  background-color: transparent;
  border-color: currentColor;
  color: var(--color-text);
}

.button--outline:hover {
  background-color: var(--color-text);
  color: var(--color-surface);
  box-shadow: none;
}

.on-deep .button--outline {
  color: var(--color-on-deep);
}

.on-deep .button--outline:hover {
  background-color: var(--color-on-deep);
  color: var(--color-text);
}
/* Forms.

   HubSpot forms are not theme assets: they are rendered by the Forms tool and
   arrive with their own class names. Styling them here is how a form embedded
   anywhere on the site inherits the brand. See context/05 Part B for the
   capture pattern these forms sit inside.

   The class names below (.hs-form, .hs-input, .hs-button, .hs-error-msg) are
   HubSpot's, not ours. Do not rename them.
*/

.hs-form label,
form label {
  display: block;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-text);
  margin-bottom: 0.4em;
}

.hs-form-required { color: var(--color-primary); }

.hs-input,
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="password"],
input[type="search"],
input[type="url"],
select,
textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--color-text);
  background-color: var(--color-surface);
  padding: 0.75em 0.9em;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.hs-input:focus,
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--palette-lavender-mist);
}

.hs-input[type="checkbox"],
.hs-input[type="radio"] {
  width: auto;
  margin-right: 0.5em;
  accent-color: var(--color-primary);
}

textarea { min-height: 8rem; resize: vertical; }

.hs-form-field { margin-bottom: 1.25rem; }

.hs-error-msg,
.hs-error-msgs label {
  color: var(--color-error);
  font-size: 0.875rem;
  margin-top: 0.35em;
}

.hs-input.invalid,
.hs-input.error { border-color: var(--color-error); }

/* A form dropped onto a dark section still has to be readable. */
.on-deep .hs-form label,
.on-deep form label { color: var(--color-on-deep); }

/* ---------------------------------------------------------------------------
   HUBSPOT V4 FORMS

   Everything above targets .hs-form / .hs-input, which is the LEGACY (V3)
   embed. A form built in HubSpot's current editor renders a different class
   tree, prefixed hsfc-, and inherits none of it. That is why the growth audit
   application rendered in Helvetica with 3px corners on a fully branded page.

   DO NOT STYLE THE hsfc- CLASSES DIRECTLY. That was tried first and loses:
   HubSpot injects ~176 inline rules AFTER the theme stylesheet, selected as
   `[data-hsfc-id="Renderer"] .hsfc-TextInput`, so a plain `.hsfc-TextInput`
   rule is out-specified and silently does nothing. Beating it means a
   specificity war against markup that is not ours and will change.

   Instead, every one of those inline rules resolves its value through a
   `--hsf-*` custom property. That is the supported theming surface: 201 of
   them, covering type, colour, radius, padding, spacing and the progress bar.
   Setting the variables wins without touching selectors, and survives HubSpot
   restructuring the form.

   Mapping brand tokens onto them is the whole integration. Confirmed against
   the live /growth-audit render 2026-08-27.

   Worth knowing before reaching for a custom build: the V4 renderer already
   ships the stepped "one question at a time" experience natively, including
   hsfc-Step and a progress bar. Styling it gets most of the quiz feel with no
   application to maintain.
--------------------------------------------------------------------------- */

.hsfc-Form,
[data-hsfc-id="Renderer"] {
  /* Global */
  --hsf-global__font-family: var(--font-body);
  --hsf-global__color: var(--color-text);
  --hsf-global__error-color: var(--color-error);

  /* Step heading and rich text */
  --hsf-heading__font-family: var(--font-head);
  --hsf-heading__color: var(--color-primary-deep);
  --hsf-richtext__font-family: var(--font-body);
  --hsf-richtext__color: var(--color-text-muted);

  /* Labels */
  --hsf-field-label__font-family: var(--font-body);
  --hsf-field-label__font-size: 0.9375rem;
  --hsf-field-label__color: var(--color-text);
  --hsf-field-label-requiredindicator__color: var(--color-primary);

  /* Text inputs and dropdowns */
  --hsf-field-input__font-family: var(--font-body);
  --hsf-field-input__font-size: 1rem;
  --hsf-field-input__color: var(--color-text);
  --hsf-field-input__background-color: var(--color-surface);
  --hsf-field-input__border-color: var(--color-border);
  --hsf-field-input__border-width: 1.5px;
  --hsf-field-input__border-style: solid;
  --hsf-field-input__border-radius: var(--radius-sm);
  --hsf-field-input__padding: 0.75em 0.9em;
  --hsf-field-input__placeholder-color: var(--color-text-muted);
  --hsf-field-dropdown-options__border-radius: var(--radius-sm);

  /* Textarea, same treatment */
  --hsf-field-textarea__font-family: var(--font-body);
  --hsf-field-textarea__font-size: 1rem;
  --hsf-field-textarea__color: var(--color-text);
  --hsf-field-textarea__border-color: var(--color-border);
  --hsf-field-textarea__border-width: 1.5px;
  --hsf-field-textarea__border-style: solid;
  --hsf-field-textarea__border-radius: var(--radius-sm);
  --hsf-field-textarea__padding: 0.75em 0.9em;
  --hsf-field-textarea__placeholder-color: var(--color-text-muted);

  /* Checkbox and radio */
  --hsf-field-checkbox__color: var(--color-primary);
  --hsf-field-checkbox__border-color: var(--color-border);
  --hsf-field-radio__color: var(--color-primary);
  --hsf-field-radio__border-color: var(--color-border);

  /* Helper and error text */
  --hsf-field-description__font-family: var(--font-body);
  --hsf-field-description__color: var(--color-text-muted);
  --hsf-field-footer__font-family: var(--font-body);
  --hsf-field-footer__color: var(--color-text-muted);
  --hsf-erroralert__font-family: var(--font-body);
  --hsf-erroralert__color: var(--color-error);
  --hsf-infoalert__font-family: var(--font-body);

  /* Buttons: the site's accent pill. */
  --hsf-button__font-family: var(--font-body);
  --hsf-button__font-size: 0.9375rem;
  --hsf-button__font-weight: 600;
  --hsf-button__background-color: var(--color-accent);
  --hsf-button__color: var(--color-on-accent);
  --hsf-button__border-color: transparent;
  --hsf-button__border-width: 1px;
  --hsf-button__border-style: solid;
  --hsf-button__border-radius: var(--radius-pill);
  --hsf-button__padding: 0.8em 1.6em;
  --hsf-button--hover__background-color: var(--color-accent-deep);
  --hsf-button--hover__color: var(--color-on-accent);
  --hsf-button--focus__background-color: var(--color-accent-deep);
  --hsf-button--focus__color: var(--color-on-accent);

  /* Progress bar. This is what makes a long application feel finite, so it
     takes the accent rather than a neutral. */
  --hsf-progressbar-trackLine__background-color: var(--color-border);
  --hsf-progressbar-progressLine__background-color: var(--color-accent);
  --hsf-progressbar-text__font-family: var(--font-body);
  --hsf-progressbar-text__font-size: 0.8125rem;
  --hsf-progressbar-text__color: var(--color-text-muted);

  /* Rhythm */
  --hsf-row__vertical-spacing: 1.15rem;
  --hsf-module__vertical-spacing: 1.5rem;
}

/* A V4 form on a dark section needs its type lifted, same as the V3 rule. */
.on-deep .hsfc-Form,
.on-deep [data-hsfc-id="Renderer"] {
  --hsf-global__color: var(--color-on-deep);
  --hsf-field-label__color: var(--color-on-deep);
  --hsf-heading__color: var(--color-on-deep);
  --hsf-progressbar-text__color: var(--color-on-deep);
}
/* Tables. Used by pricing comparisons and blog content. */

table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1.5rem;
  font-size: 1rem;
}

caption {
  caption-side: bottom;
  padding-top: 0.75rem;
  font-size: 0.875rem;
  color: var(--color-text-muted);
  text-align: left;
}

th, td {
  padding: 0.85em 1em;
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  vertical-align: top;
}

thead th {
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--color-text);
  background-color: var(--color-surface-alt);
  border-bottom-width: 2px;
}

tbody tr:last-child td { border-bottom: 0; }

/* Components: styling for HubSpot's own default modules when they appear in a
   dnd area. Our own modules carry their CSS in their module.css, which HubSpot
   includes only when the module is on the page. */
/* Menu and simple menu */

.hs-menu-wrapper ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding-left: 0;
}

/* Horizontal menu */

.hs-menu-wrapper.hs-menu-flow-horizontal .hs-menu-children-wrapper {
  flex-direction: column;
}

@media (max-width: 767px) {
  .hs-menu-wrapper.hs-menu-flow-horizontal ul {
    flex-direction: column;
  }
}

/* Vertical menu */

.hs-menu-wrapper.hs-menu-flow-vertical ul {
  flex-direction: column;
}

/* Flyouts */

.hs-menu-wrapper.hs-menu-flow-vertical.flyouts ul {
  display: inline-flex;
}

@media (max-width: 767px) {
  .hs-menu-wrapper.hs-menu-flow-vertical ul {
    display: flex;
  }
}

.hs-menu-wrapper.flyouts .hs-item-has-children {
  position: relative;
}

.hs-menu-wrapper.flyouts .hs-menu-children-wrapper {
  left: -9999px;
  opacity: 0;
  position: absolute;
}

.hs-menu-wrapper.flyouts .hs-menu-children-wrapper a {
  display: block;
  white-space: nowrap;
}

.hs-menu-wrapper.hs-menu-flow-horizontal.flyouts .hs-item-has-children:hover > .hs-menu-children-wrapper {
  left: 0;
  opacity: 1;
  top: 100%;
}

.hs-menu-wrapper.hs-menu-flow-vertical.flyouts .hs-item-has-children:hover > .hs-menu-children-wrapper {
  left: 100%;
  opacity: 1;
  top: 0;
}

@media (max-width: 767px) {
  .hs-menu-wrapper.flyouts .hs-menu-children-wrapper,
  .hs-menu-wrapper.hs-menu-flow-horizontal.flyouts .hs-item-has-children:hover > .hs-menu-children-wrapper,
  .hs-menu-wrapper.hs-menu-flow-vertical.flyouts .hs-item-has-children:hover > .hs-menu-children-wrapper {
    left: 0;
    opacity: 1;
    position: relative;
    top: auto;
  }
}

/* CTA, logo, and rich text images */

.hs_cos_wrapper_type_cta img,
.hs_cos_wrapper_type_logo img,
.hs_cos_wrapper_type_rich_text img {
  height: auto;
  max-width: 100%;
}

/* Utilities: last so they can override */
/* Surface treatment.

   Deliberately almost nothing. Three CSS pattern systems were tried here (a
   coloured glow, a line grid, and an embossed triangular lattice with nodes)
   and all three were rejected: at low contrast they read as graph paper, and at
   any higher contrast they fight the type.

   What the reference sites actually do is simpler than a pattern. Ripe Planet
   is a flat deep teal. Alora is one photographic metallic surface. Tavus is
   warm paper with a whisper of grain. None of them draw a pattern in CSS.

   So this file now offers only grain, and a photographic surface goes in as an
   image when there is one to use. A generated pattern is not a substitute for a
   real texture, and pretending otherwise cost three rounds of review.
*/

.texture { position: relative; isolation: isolate; }
.texture > * { position: relative; z-index: 1; }

.texture::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Fine film grain. Inlined SVG turbulence, so it costs no request. */
.texture--grain::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  opacity: 0.14;
  mix-blend-mode: overlay;
}

/* Photographic surface. Set --texture-image on the section to use it; the
   image is dimmed and sits under the content. This is the slot a real texture
   drops into, and it stays empty until there is an approved asset. */
.texture--image::before {
  background-image: var(--texture-image, none);
  background-size: cover;
  background-position: center;
  opacity: var(--texture-image-opacity, 0.35);
}

/* A hairline rule that fades out at both ends. Useful between sections. */
.rule-fade {
  border: 0;
  height: 1px;
  background: linear-gradient(to right, transparent, var(--color-border), transparent);
  margin: 0;
}
/* Scroll-reveal motion.

   NOTE ON COMMENTS IN CSS FILES: never write an HTML tag name in angle brackets
   here, not even inside a comment. HubSpot validates .css uploads and rejects
   the whole theme with "Can not save html to a css file". Write "the root html
   element", not the tag.


   The current romandamedia.com does this with animate.css plus WOW.js, two
   libraries and two extra requests. IntersectionObserver plus these keyframes
   does the same job in about thirty lines of JS and nothing to download.

   THE RULE FOR THIS THEME: motion is a garnish. It reveals content that is
   already there and readable. It never gates content behind an animation, and
   never moves anything the reader is trying to read.
*/

[data-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

[data-reveal="left"]  { transform: translate3d(-28px, 0, 0); }
/* A longer throw than the other directions. This is the partner badge, the one
   element on the page whose arrival is meant to be noticed. */
[data-reveal="right"] { transform: translate3d(28px, 0, 0); }
[data-reveal="right-far"] { transform: translate3d(90px, 0, 0); opacity: 0; transition-duration: 0.85s; }
[data-reveal="scale"] { transform: scale(0.96); }

/* HORIZONTAL REVEALS WIDEN A NARROW PAGE.

   A transform still contributes to the document scroll width. At 375px the
   badge band's 90px throw pushed the page wider than the viewport, which read
   as a strip of background down the right edge plus real horizontal scrolling,
   and then "fixed itself" the moment the element revealed and the transform
   cleared. Reported from mobile 2026-08-27.

   Below the mobile breakpoint every horizontal reveal falls back to the default
   vertical one. The motion still reads as motion, and nothing can widen the
   page. Fixing it here rather than with overflow-x on a wrapper is deliberate:
   a clipping ancestor would break the fixed header. */
@media (max-width: 767px) {
  [data-reveal="left"],
  [data-reveal="right"],
  [data-reveal="right-far"] {
    transform: translate3d(0, 18px, 0);
  }
}

[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Stagger children without writing a delay per element. */
[data-reveal-group] > * { transition-delay: calc(var(--i, 0) * 90ms); }

/* NO-JS SAFETY NET. If the observer never runs, every revealed element would
   stay at opacity 0 and the page would look empty. This class is added to
   the root html element by the motion script itself, so content is only
   ever hidden when something is definitely there to reveal it. */
html:not(.js-motion) [data-reveal] {
  opacity: 1;
  transform: none;
}

/* Marquee, for the logo strip. Duplicated content scrolls seamlessly. */
.marquee {
  display: flex;
  overflow: hidden;
  gap: var(--marquee-gap, 3.5rem);
  /* Black here is an ALPHA STOP, not a colour: in a mask, opaque means
     visible. Written as rgb() so the brand-colour check does not flag it. */
  mask-image: linear-gradient(to right, transparent, rgb(0 0 0) 8%, rgb(0 0 0) 92%, transparent);
}

.marquee__track {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--marquee-gap, 3.5rem);
  padding-right: var(--marquee-gap, 3.5rem);
  animation: marquee-scroll var(--marquee-duration, 38s) linear infinite;
}

.marquee:hover .marquee__track { animation-play-state: paused; }

@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

/* Respect the setting. Someone who has asked their operating system for less
   motion has usually asked for a reason, and a marquee is exactly the kind of
   perpetual movement that triggers vestibular symptoms. Reveals resolve
   instantly rather than being removed, so nothing disappears. */
@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .marquee__track { animation: none; }
  .marquee { mask-image: none; flex-wrap: wrap; justify-content: center; }
}
/* For content that needs to be visually hidden but stay visible for screenreaders */

.show-for-sr {
  border: 0 !important;
  clip: rect(0, 0, 0, 0) !important;
  height: 1px !important;
  overflow: hidden !important;
  padding: 0 !important;
  position: absolute !important;
  white-space: nowrap !important;
  width: 1px !important;
}

@media (max-width: 767px) {
  .show-for-sr--mobile {
    border: 0 !important;
    clip: rect(0, 0, 0, 0) !important;
    height: 1px !important;
    overflow: hidden !important;
    padding: 0 !important;
    position: absolute !important;
    white-space: nowrap !important;
    width: 1px !important;
  }
}