/**
 * ProofDocs application-specific CSS overrides and custom components.
 *
 * This stylesheet extends the Falcon Bootstrap 5 theme with ProofDocs-specific
 * styles. pages/base.html loads it after theme.min.css and before the consent
 * library's cookieconsent.css.
 *
 * Accessibility notes:
 * - All animations and transitions respect prefers-reduced-motion (WCAG 2.3.3).
 * - Hover effects are gated behind @media (hover: hover) so touch devices do not
 *   get stuck in a hover state after tap (sticky-hover bug on iOS/Android).
 * - forced-colors disables decorative box-shadows and gradients so Windows High
 *   Contrast Mode can repaint affordances with system colors.
 */

/* Global CSS custom properties for consistent theming across the application. */
/* Brand colors live in Falcon variables (--falcon-primary, --falcon-info, --falcon-warning, etc.). */
/* This block holds nineteen declarations in six groups, not one: the four */
/* --badge-*-hover tones, which a .badge cannot read from --falcon-btn-hover-bg */
/* because it sits in no .btn-* context; --pd-ink-on-brand-fill plus the two */
/* --pd-shadow-sticky* and the two --pd-shadow-card-hover*, for which Falcon ships no */
/* upward-facing and no hover shadow token; the four --pd-*-fill* values of the filled */
/* surfaces that carry white text; the three --pd-paper-* / --pd-placeholder-* */
/* tokens of the document sheet; the two --pd-transition-* durations; and --light-bg, */
/* which is plain white and predates the rest. Fifteen of the nineteen have nothing to */
/* do with badges - see each declaration's own comment below. The count is a premise */
/* of the reasoning above it, so it is re-counted whenever a declaration is added or */
/* removed: it said eleven while a fifth badge tone had already gone on 22.08.2026 and */
/* two card-hover shadows had arrived, which is two errors cancelling to a wrong number */
/* in the middle. --light-grey and --dark-text, pinned for the former consent banner, */
/* left on 10.10.2026: nothing read them since vanilla-cookieconsent replaced it. */
:root {
  --light-bg: #ffffff;

  /* Badge hover fills. These are not free values: each one is Falcon's own
     button hover shade for that variant, which the theme defines as
     --falcon-btn-hover-bg but only inside the .btn-<variant> scope — a .badge
     sits in no such scope and cannot read it, which is why the value is
     repeated here rather than referenced. Deriving it instead
     (color-mix(in srgb, var(--falcon-primary) 85%, black)) reproduces three of
     the four exactly but lands one channel off on success (178 vs 179, the
     browser rounds 178.5 down), so the literals stay. A fifth value existed for
     the secondary variant and was removed on 22.08.2026: no bg-secondary badge
     in this project sits inside an anchor, so the rule that read it never
     matched. They are pinned against
     theme.min.css by tests/test_theme_derived_values.py, so a theme upgrade
     that moves a shade cannot leave these silently behind. */
  --badge-primary-hover: #2569c3; /* .btn-primary  --falcon-btn-hover-bg */
  --badge-info-hover: #21a0d7; /* .btn-info     --falcon-btn-hover-bg */
  --badge-success-hover: #00b368; /* .btn-success  --falcon-btn-hover-bg */
  --badge-warning-hover: #d06d35; /* .btn-warning  --falcon-btn-hover-bg */

  /* Ink for text sitting on one of the light brand fills (info, warning, success).
     Deliberately a literal and NOT --falcon-gray-1100: Falcon inverts its whole gray
     scale with the theme, so gray-1100 resolves to #0b1727 in light mode but #f9fafd
     in dark mode. The three fills themselves are brand colours and stay identical in
     both themes, so an ink that follows the theme lands back on near-white and
     reproduces the very contrast failure it was introduced to remove — measured on the
     dark report page: #f9fafd on #00d27a is 1.92:1. This value is the light-mode value
     of gray-1100 and measures 9.00 / 8.32 / 6.89 on success / info / warning. */
  --pd-ink-on-brand-fill: #0b1727;

  /* The fills of the owner's decision of 20.08.2026 (the rule "Filled brand surfaces
     that carry white text" further down): white measures 4.60:1 and 4.56:1 on them,
     4.14:1 and 4.16:1 on the plain --falcon-primary and --falcon-danger. */
  --pd-primary-fill: #1d72e3;
  --pd-primary-fill-rgb: 29, 114, 227;
  --pd-danger-fill: #e32346;
  --pd-danger-fill-rgb: 227, 35, 70;

  /* The sheet of a created document is white in both modes, because the buyer reads it
     as the page they will print; its ink is the light-mode gray-1000 for the same
     reason, and the placeholder marks are the light warning tint under the sheet's ink. */
  --pd-paper-bg: #fff;
  --pd-paper-ink: #232e3c;
  --pd-placeholder-bg: #fde6d8;

  /* Upward shadow of the two fixed bottom bars (.sticky-cta-bar on the formular
     pages, .pd-sticky-cta on the reporting pages). Falcon's four box-shadow tokens
     all cast downward, so neither bar can use one; the value was therefore written
     out — and each of the two bars carried its own light and dark copy, four
     declarations for two distinct shadows. Two of them being verbatim duplicates is
     how the pair drifts: darkening one bar and forgetting the other. */
  --pd-shadow-sticky: 0 -4px 16px rgba(20, 30, 60, 0.08);
  --pd-shadow-sticky-dark: 0 -4px 16px rgba(0, 0, 0, 0.5);

  /* Hover lift of the related-article cards, in the same shape and for the same
     reason as the sticky pair above: an 8 % black shadow is invisible on the
     near-black dark-mode card, so the light and the dark value are two distinct
     shadows rather than one. Written out as a pair here so darkening one and
     forgetting the other is not possible — which is exactly the drift the comment
     on the sticky tokens warns about, and which these two values were still open
     to. */
  --pd-shadow-card-hover: 0 4px 12px rgba(0, 0, 0, 0.08);
  --pd-shadow-card-hover-dark: 0 4px 12px rgba(0, 0, 0, 0.45);

  /* Transition durations. Nine declarations carried four different durations, and two
     of the differences were not decisions: .footer-brand faded in 0.15s beside
     .footer-link at 0.2s in the same footer row, and .demo-image-hover-* animated the
     exact same three properties as .related-article-card — transform, box-shadow,
     border-color — at 0.3s against 0.2s. Gleichartige Bewegungen must feel the same,
     so both were pulled onto the base value. The slow value survives for .badge alone,
     which is a colour cross-fade rather than a movement and reads better unhurried.
     The easing is `ease` throughout without a single exception and is part of the
     token, so a later change cannot move duration and curve apart. Every user of these
     sits inside @media (prefers-reduced-motion: no-preference), which is unchanged. */
  --pd-transition-base: 0.2s ease;
  --pd-transition-slow: 0.3s ease;
}

/* Enable smooth scrolling behavior for better user experience. */
/* Respects prefers-reduced-motion for users with vestibular disorders (WCAG 2.3.3). */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Keep the sticky chrome out of the way when the browser scrolls something into view.
   Reserving space at the end of the document (further down this file) stops the last
   card from being covered, but it does nothing for the browser's own scroll-into-view:
   that stops as soon as the element touches the viewport edge, which is exactly where
   the fixed bar sits. Tabbing through the Arbeitszeugnisanalyse form at 768 px, nine
   stops were measured as 100 % hidden behind the bar at the moment they took focus —
   among them the upload field and both consent switches — which is a failure of WCAG 2.2
   SC 2.4.11 (Focus Not Obscured, AA). scroll-padding tells the browser where the usable
   viewport really ends; it also fixes the #activation anchor, which used to land under
   the navbar. The bottom values match the reserves used further down, so bar height and
   scroll padding cannot drift apart.

   The top value carries a second job that is easy to remove by accident. Every product
   badge on the home page links to /<produkt>/formular/#form, and the cost statement of
   each form page sits in the alert immediately above that anchor. Measured on
   16.09.2026 across four products and six widths from 320 to 1920 px: the jump leaves
   that statement on screen in all 24 cells.

   It does so because of two offsets, and this padding is only one of them — the figures
   are written out because an earlier version of this comment credited it with the whole
   effect and the measurement said otherwise. At 1440 px the price line lands at 100 px
   with both offsets, at 28 px with the theme's scroll-margin alone, at 7 px with this
   padding alone, and at **-65 px, off screen, with neither**. So either one carries it,
   barely, and removing both scrolls past the one sentence that answers what the product
   costs — on the most common entry into the funnel.

   The other offset is Falcon's ``scroll-margin-top: calc(--falcon-top-nav-height +
   1.5rem)`` in the compiled theme, which is a third-party value a theme update can
   change without anyone here noticing. That is the argument for keeping this one: it is
   the half of the margin this project controls. tests/test_css_accessibility_rules.py
   pins it. */
html {
  scroll-padding-top: 4.5rem;
}

html:has(.sticky-cta-bar) {
  scroll-padding-bottom: 4.5rem;
}

html:has(.pd-sticky-cta) {
  scroll-padding-bottom: 9rem;
}

/* The scroll padding has to follow the same breakpoint as the content padding
   below, or an anchor jump on the desktop reserves the mobile bar's height and
   leaves a visible gap. Measured on the locked reports (design run of 10.10.2026):
   the bar is 57 px from 992 px up, but 92 to 122 px between 768 and 991 px, where
   the price and button group leaves the guarantee line under 100 px and it wraps. */
@media (min-width: 992px) {
  html:has(.pd-sticky-cta) {
    scroll-padding-bottom: 4.5rem;
  }
}

/* The same correction for the form pages' bar, which the rule above had not
   received. `.sticky-cta-bar` is display:none from 992 px up, but :has() is
   structural and does not read display, so the 72 px stayed reserved for a bar
   that is never painted. Measured on the JTA form at 1280 and 1440 px:
   scrollIntoView({block:'nearest'}) on the last form row scrolled to 67 px
   instead of 0. The breakpoint is 992 px, not 768 px, because that is where
   this bar hides - the reserve below uses the same one. */
@media (min-width: 992px) {
  html:has(.sticky-cta-bar) {
    scroll-padding-bottom: 0;
  }
}

@media (max-width: 339.98px) {
  html:has(.sticky-cta-bar) {
    scroll-padding-bottom: 6rem;
  }
}

/* Override Falcon theme footer positioning to prevent content overlap. */
/* The theme uses absolute positioning with a fixed padding-bottom, which breaks with taller footers. */
/* Flexbox column layout ensures the footer always sits below the content regardless of height. */
/* The !important here beats Falcon's own rule and is legitimate. The value behind it
   is a custom property so that the reserves below (four since 10.10.2026) can set it
   by ordinary cascade: before, each of them had to beat this declaration with an
   !important of its own — six declarations, five values, one property, and the winner
   readable only from the line number rather than from the cascade. A further
   breakpoint can now be added without another !important. */
.content {
  display: flex;
  flex-direction: column;
  padding-bottom: var(--pd-content-pad-bottom, 0) !important;
}

.content > main {
  flex: 1 0 auto;
}

.footer {
  position: static !important;
  flex-shrink: 0;
}

/* The hamburger is a flex item of the top navigation with flex-shrink: 1 and no width
   floor of its own, so as soon as the row runs short it is the element that gives way:
   measured at 20 x 40 px at 320, 375 and 576-620 px, against 40 x 40 px everywhere else.
   Below 24 px it misses WCAG 2.2 SC 2.5.8 (AA), and the spacing exception does not apply
   because the logo link sits 4 px away — on a phone this is the only route into the
   navigation. The row has 17-26 px of slack in exactly those bands, so the 4 px this
   floor costs are affordable; the two size rules further down this file already trade
   the same slack for the logo and the theme toggle. */
.navbar-toggler {
  min-width: 24px;
}

/* Footer navigation links rendered as quiet pills that adopt the brand colour on hover and keyboard focus. */
.footer-link {
  display: inline-block;
  padding: 0.2rem 0.55rem;
  border-radius: var(--falcon-border-radius-lg);
  /* Fallback is #5e6e82, the value this file measures at 5.21:1 further down and the
     one the second --falcon-gray-700 fallback already carried. The #4d5969 that stood
     here was 8.4 % off and backed by no measurement in this project: a theme update
     or a stylesheet that fails to load would have rendered this link in a tone nothing
     vouches for. */
  color: var(--falcon-gray-700, #5e6e82);
  text-decoration: none;
  line-height: var(--falcon-body-line-height);
}

/* Focus stays ungated in both directions. A keyboard user exists on touch devices
   too, and prefers-reduced-motion must never remove a focus affordance — only its
   animation. */
/* The ink is the corrected link colour: the brand blue on its 8 % tint measured 3.36:1
   in light and 4.35:1 in dark mode (design run of 10.10.2026). */
.footer-link:focus-visible {
  color: rgb(var(--falcon-link-color-rgb));
  background-color: rgba(var(--falcon-primary-rgb), 0.08);
}

/* Hover behind (hover: hover) so a tap does not leave the link stuck in its hover
   state on iOS and Android, and the transition behind prefers-reduced-motion — the
   two guarantees the file header makes for every rule in this stylesheet. */
@media (hover: hover) {
  .footer-link:hover {
    color: rgb(var(--falcon-link-color-rgb));
    background-color: rgba(var(--falcon-primary-rgb), 0.08);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .footer-link {
    transition:
      color var(--pd-transition-base),
      background-color var(--pd-transition-base);
  }
}

/* Footer brand mark in the baseline row; sits beside the copyright and cookie button. */
/* The vertical padding is load-bearing, not decoration: without it the link box is the
   bare height of its 18 px logo and its line, measured at 110 x 20 px on every page and
   every width, which is under the 24 px floor of WCAG 2.2 SC 2.5.8 (AA). Four pixels top
   and bottom lift it to 28 px; the baseline row is a wrapping flex row with room to
   spare, so nothing else moves. */
.footer-brand {
  color: var(--falcon-gray-800, #344050);
  padding: 0.25rem 0;
}

/* Same two gates as .footer-link above. */
@media (hover: hover) {
  .footer-brand:hover {
    opacity: 0.85;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .footer-brand {
    transition: opacity var(--pd-transition-base);
  }
}

/* Boundary contrast of the form controls (WCAG 2.2 SC 1.4.11, AA, 3:1).
   Measured on /kontakt/ and all four product forms, both themes: the theme's
   --falcon-border-color puts a 1px #d8e2ef edge on white, which is 1.31:1, and
   #344050 on the dark card, which is 1.60:1. The switches sit at 1.82 and 2.36:1.
   With a floating label the border is the ONLY thing that says a field is there, so
   an empty field practically disappears into the card — on the two paid analysis
   products that includes the mandatory upload (1.16:1 against the page).
   --falcon-gray-600 (#748194) is the LIGHTEST token this project already owns that
   clears 3:1 in both themes: measured 3.95:1 on the light field and 4.25 to 4.55:1
   on the dark one, and it happens to be theme-invariant, so one rule covers both.
   No new value enters the project - it is also --falcon-secondary.
   Deliberately scoped to the controls: 1.4.11 asks for the boundary of a USER
   INTERFACE COMPONENT. Card borders, table rules and dividers are decoration and
   keep the lighter tone, so the calm of the pages is untouched. axe does not test
   1.4.11 for a form border, which is why the accessibility run reported zero. */
.form-control,
.form-select,
.form-check-input {
  border-color: var(--falcon-gray-600);
}

/* File upload drop zone component with dashed border styling. */
.filezone {
  border: 2px dashed var(--falcon-border-color);
  border-radius: var(--falcon-border-radius-lg);
  text-align: center;
  background-color: var(--falcon-body-bg);
}

/* Active state styling when files are dragged over the drop zone. Uses the
   theme-aware primary subtle background so the highlight visibly differs from the
   resting --falcon-body-bg in both light and dark mode. The former
   --falcon-input-bg variable was undefined, so the rule was invalid at
   computed-value time and the zone fell back to transparent (no drop feedback). */
/* :focus-within joins .dragover here because the zone had feedback for the pointer
   and none for the keyboard: tabbing to the file input inside it changed nothing on
   the zone itself, so the only upload control of the two analysis products gave a
   keyboard user no sign of where the focus had landed. Same declaration, same
   visual language - no new state is being invented, the existing one is extended to
   the second input method. The input's own focus ring is unaffected. */
.filezone.dragover,
.filezone:focus-within {
  background-color: var(--falcon-primary-bg-subtle);
}

/* The native file selector button in the brand fill. White text needs the fill of the
   owner's decision of 20.08.2026: on the plain primary it measured 4.14:1. */
input[type="file"]::file-selector-button {
  background-color: var(--pd-primary-fill) !important;
  color: var(--light-bg) !important;
}

/* Resting look of a submit button whose consent switches are not both ticked.
   0.65 is stock Bootstrap's disabled opacity, but THIS theme fades a genuinely
   disabled button to 0.5 (--falcon-btn-disabled-opacity), so the two do not look
   alike and the value is not being aligned: the button here is still operable, and
   fading an operable control further than a dead one costs legibility for no gain.
   Wahrnehmbarkeit before Systemtreue. It deliberately omits
   pointer-events: none, because the button is no longer disabled: it stays in the
   tab order and in the accessibility tree so it can announce itself and explain the
   refusal (see initializeCheckboxToggle in custom.js). Suppressing pointer events
   here would silently restore the old behaviour for mouse users, who would click a
   dead control and receive nothing. */
.pd-consent-pending {
  opacity: 0.65;
  cursor: not-allowed;
}

/* Consent banner (vanilla-cookieconsent, vendors/cookieconsent/, since 08.10.2026).
   The library places itself at the maximum z-index; 1045 keeps the prompt above the
   sticky purchase bar and the navbar (1030) but below Bootstrap modals (1055) and
   tooltips (1080), so a consent prompt never hides a modal dialog, as the TermsFeed
   rules before it did. The site font replaces the library's system stack; `inherit`
   did not, because on a custom property it inherits the library's own value from
   :root. Its own button colours stay: the brand primary would put white text at about
   4:1, below the 4.5:1 WCAG AA asks for. */
#cc-main {
  --cc-z-index: 1045;
  --cc-font-family: var(--falcon-body-font-family);
}

/* The library loads after this file, so these rules carry one more element to win.
   Its category switches measured 50 x 23 px, under the 24 px of WCAG 2.2 SC 2.5.8 with
   the section title too close for the spacing exception; the knob grows with them. */
html #cc-main .section__toggle,
html #cc-main .section__toggle-wrapper,
html #cc-main .toggle__icon,
html #cc-main .toggle__label,
html #cc-main .toggle__icon-circle {
  height: 24px;
}

html #cc-main .toggle__icon-circle {
  width: 24px;
}

html #cc-main .section__toggle:checked ~ .toggle__icon .toggle__icon-circle {
  transform: translateX(26px);
}

/* The prompt is 366 to 388 px high and did not scroll: on a phone in landscape its title
   started above the window (740 x 360). It now stays inside the window and scrolls. */
html #cc-main .cm {
  max-height: calc(100vh - 1rem);
  max-height: calc(100dvh - 1rem);
  overflow-y: auto;
}

/* Highlight active navigation links with primary brand color. */
.navbar-top .navbar-nav .nav-link.active {
  color: var(--falcon-primary) !important;
}

/* Apply hover and focus states to navigation links for better interactivity. */
.navbar-top .navbar-nav .nav-link.text-body:hover,
.navbar-top .navbar-nav .nav-link.text-body:focus {
  color: var(--falcon-nav-link-hover-color) !important;
}

/* Apply pulse animations to CTA buttons for visual emphasis and user attention. */
/* Both variants are gated behind prefers-reduced-motion (WCAG 2.3.3); the keyframes */
/* themselves stay outside the media query so the rule remains valid even if an external */
/* stylesheet later opts a single element into the animation. Two rounds of 2 s, then */
/* the button rests: running endlessly beside the report it needed a way to stop it */
/* (WCAG 2.2 SC 2.2.2, which exempts motion of 5 s or less). The pulsing buttons carry */
/* no shadow-sm: that utility is !important and outranked the animated ring. */
@media (prefers-reduced-motion: no-preference) {
  .pulse {
    animation: pulse-animation 2s 2;
  }

  .pulse-info {
    animation: pulse-info-animation 2s 2;
  }
}

/* Pulse keyframes for the primary CTA: scales up and emits a fading ring. The ring reads
   --pd-pulse-rgb, which the product colours below set, so a green or orange purchase
   button no longer pulses with a blue ring; without it the ring stays primary. */
@keyframes pulse-animation {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(var(--pd-pulse-rgb, var(--falcon-primary-rgb)), 0.7);
  }

  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(var(--pd-pulse-rgb, var(--falcon-primary-rgb)), 0);
  }

  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(var(--pd-pulse-rgb, var(--falcon-primary-rgb)), 0);
  }
}

.btn-success.pulse {
  --pd-pulse-rgb: var(--falcon-success-rgb);
}

.btn-warning.pulse {
  --pd-pulse-rgb: var(--falcon-warning-rgb);
}

.btn-danger.pulse {
  --pd-pulse-rgb: var(--falcon-danger-rgb);
}

.btn-secondary.pulse {
  --pd-pulse-rgb: var(--falcon-secondary-rgb);
}

/* Pulse keyframes for the info CTA: scales up and emits a fading ring using the Falcon info RGB token. */
@keyframes pulse-info-animation {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(var(--falcon-info-rgb), 0.7);
  }

  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(var(--falcon-info-rgb), 0);
  }

  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(var(--falcon-info-rgb), 0);
  }
}

/* Demo image hover effect for primary-colored product GIFs. */
.demo-image-hover-primary {
  cursor: pointer;
}

/* Demo image hover effect for warning-colored product GIFs. */
.demo-image-hover-warning {
  cursor: pointer;
}

/* Apply hover transitions and transforms only when:
 *   1. the user has no motion preference (WCAG 2.3.3), AND
 *   2. the primary pointer is a real hover-capable device (mouse/trackpad).
 * On touch screens the :hover state stays "stuck" after a tap until the user
 * taps elsewhere, leaving the demo image visibly scaled — wrapping in
 * @media (hover: hover) suppresses that on phones and tablets. */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .demo-image-hover-primary {
    transition:
      transform var(--pd-transition-base),
      box-shadow var(--pd-transition-base),
      border-color var(--pd-transition-base);
  }

  .demo-image-hover-primary:hover {
    transform: scale(1.02) translateY(-2px);
    box-shadow: 0 12px 30px rgba(var(--falcon-primary-rgb), 0.2);
    border-color: var(--falcon-primary) !important;
  }

  .demo-image-hover-warning {
    transition:
      transform var(--pd-transition-base),
      box-shadow var(--pd-transition-base),
      border-color var(--pd-transition-base);
  }

  .demo-image-hover-warning:hover {
    transform: scale(1.02) translateY(-2px);
    box-shadow: 0 12px 30px rgba(var(--falcon-warning-rgb), 0.2);
    border-color: var(--falcon-warning) !important;
  }
}

/* Add smooth transition effect for badge background color changes. */
/* Respects prefers-reduced-motion for users with vestibular disorders (WCAG 2.3.3). */
@media (prefers-reduced-motion: no-preference) {
  .badge {
    transition: background-color var(--pd-transition-slow);
  }
}

/* Darken primary badge color on parent anchor hover for visual feedback. */
@media (hover: hover) {
  a:hover .badge.bg-primary {
    background-color: var(--badge-primary-hover) !important;
  }
}

/* Darken info badge color on parent anchor hover for visual feedback. */
@media (hover: hover) {
  a:hover .badge.bg-info {
    background-color: var(--badge-info-hover) !important;
  }
}

/* Darken success badge color on parent anchor hover for visual feedback. */
@media (hover: hover) {
  a:hover .badge.bg-success {
    background-color: var(--badge-success-hover) !important;
  }
}

/* Darken warning badge color on parent anchor hover for visual feedback. */
@media (hover: hover) {
  a:hover .badge.bg-warning {
    background-color: var(--badge-warning-hover) !important;
  }
}

/* Apply primary color to FAQ h3 headings within card bodies for consistent styling. */
/* Excludes Kündigungsanalyse (text-warning) and Arbeitszeugniserstellung (text-info) per product color scheme. */
.card-body h3.h6:not(.text-warning):not(.text-info) {
  color: var(--falcon-primary);
}

/* Hide Django-Daisy SVG icons in checkbox labels to maintain classic checkbox appearance. */
.toggle svg {
  display: none !important;
}

/* Ensure toggle labels do not create unwanted spacing or layout shifts. */
/* Using display:contents makes the toggle wrapper invisible to layout while keeping its children. */
.toggle {
  padding: 0 !important;
  margin: 0 !important;
  display: contents !important;
}

/* Reset toggle label styling to prevent DaisyUI interference with checkbox layout. */
.toggle::before,
.toggle::after {
  content: none !important;
  display: none !important;
}

/* Maintain proper alignment for checkboxes without toggle styling effects. */
.form-check .toggle {
  background: none !important;
  border: none !important;
  width: auto !important;
  height: auto !important;
}

/* Force checkbox and label side-by-side alignment on all screen sizes. */
.form-switch .form-check {
  display: flex !important;
  align-items: flex-start !important;
  padding-left: 0 !important;
}

/* Position the checkbox input correctly within the flex container. */
.form-switch .form-check .form-check-input {
  float: none !important;
  margin-left: 0 !important;
  margin-top: 0.1875rem;
  flex-shrink: 0;
}

/* Ensure the label text flows naturally beside the checkbox. */
.form-switch .form-check .form-check-label {
  margin-left: 0.5rem;
}

/* A switch with a help text: crispy puts the text into the same flex row as a third
   column, where it touched the label ("Sprinterklausel" at 375 px). It takes its own
   line, aligned with the label text: the 2em switch is measured in the field's font,
   the help text runs at 75 % of it, so 2em become 2.6667em there, plus the label's
   0.5rem. The label takes the rest of the first line and wraps inside it; with its
   automatic flex basis a long consent label fell below its switch once the row could
   wrap (design run of 10.10.2026). */
.form-switch .form-check {
  flex-wrap: wrap;
}

.form-switch .form-check .form-check-label {
  flex: 1 1 0;
  min-width: 0;
}

.form-switch .form-check > .form-text {
  flex-basis: 100%;
  margin-left: calc(2.6667em + 0.5rem);
}

/* Shared base styles for product demo videos in CTA sections, to avoid inline style repetition. */
/* The explicit aspect-ratio reserves the box before anything is loaded. With             */
/* preload="none" the width/height attributes alone did not: Chrome treated the <video>   */
/* as unsized until its poster arrived, and the box then grew and pushed the cards below  */
/* it down (CLS 0.25 on a throttled mobile trace of the pillar article, 23.09.2026). All  */
/* three posters and videos are 960 x 600, hence 16 / 10.                                 */
.demo-video {
  border-width: 2px !important;
  width: 100%;
  height: auto;
  max-width: 100%;
  aspect-ratio: 16 / 10;
}

/* Primary-colored gradient background for analysis product demo videos. */
/* The light endpoint uses the Falcon emphasis-bg token (the card surface, white in light */
/* mode, dark navy in dark mode) so the wash adapts to the active theme instead of staying */
/* white. In light mode --falcon-emphasis-bg-rgb is 255,255,255, preserving the original look. */
.demo-video-primary {
  background: linear-gradient(
    135deg,
    rgba(var(--falcon-primary-rgb), 0.05) 0%,
    rgba(var(--falcon-emphasis-bg-rgb), 0.95) 100%
  );
}

/* Warning-colored gradient background for termination product demo videos. */
/* Same theme-aware light endpoint as .demo-video-primary (see note above). */
.demo-video-warning {
  background: linear-gradient(
    135deg,
    rgba(var(--falcon-warning-rgb), 0.05) 0%,
    rgba(var(--falcon-emphasis-bg-rgb), 0.95) 100%
  );
}

/* Sticky CTA bar on mobile for formular pages. */
/* Keeps the submit button visible at the bottom of the viewport on small screens. */
@media (max-width: 991.98px) {
  .sticky-cta-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1030;
    background: var(--falcon-body-bg);
    border-top: 1px solid var(--falcon-border-color);
    padding: 0.75rem 1rem;
    box-shadow: var(--pd-shadow-sticky);
  }

  /* Stronger upward shadow in dark mode to keep the bar visually separated from the dark page. */
  [data-bs-theme="dark"] .sticky-cta-bar {
    box-shadow: var(--pd-shadow-sticky-dark);
  }

  body:has(.sticky-cta-bar) .content {
    --pd-content-pad-bottom: 4.5rem;
  }
}

/* Related articles section styling for consistent visual integration with blog content. */
.related-articles {
  border-top: 1px solid var(--falcon-border-color);
}

/* Related articles header styling matching article heading conventions. */
.related-articles-header {
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--falcon-border-color);
}

/* Related article card hover and transition effects for interactive feedback. */
/* Respects prefers-reduced-motion (WCAG 2.3.3) and is gated behind hover: hover so the */
/* effect does not stick on touch devices after a tap. */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .related-article-card {
    transition:
      transform var(--pd-transition-base),
      box-shadow var(--pd-transition-base),
      border-color var(--pd-transition-base);
  }

  .related-article-card:hover,
  .related-article-card:focus-within {
    transform: translateY(-2px);
    box-shadow: var(--pd-shadow-card-hover);
    border-color: var(--falcon-primary) !important;
  }

  /* An 8 % black shadow is invisible on the near-black dark-mode card background, */
  /* so the hover lift loses its depth cue. Matches the sticky-bar override above. */
  [data-bs-theme="dark"] .related-article-card:hover,
  [data-bs-theme="dark"] .related-article-card:focus-within {
    box-shadow: var(--pd-shadow-card-hover-dark);
  }

  .related-article-card.related-article-card--warning:hover,
  .related-article-card.related-article-card--warning:focus-within {
    border-color: var(--falcon-warning) !important;
  }

  .related-article-arrow {
    transition:
      transform var(--pd-transition-base),
      color var(--pd-transition-base);
  }

  /* The hover tone is the theme-aware `*-text-emphasis`, not the raw brand token,
     for the same reason the link and button rules further down carry it. Measured
     on 16.09.2026 with the pointer on the card, against the effective background
     walked up the ancestor chain: the raw token gave 4.06:1 on the dark card and
     4.14:1 on the light one, both short of the 4.5:1 of WCAG 2.2 AA (1.4.3); the
     emphasis tone gives 10.00:1 and 6.58:1. The same correction was made for the
     ratgeber arrows below, measured at 3.88:1 -> 9.56:1 dark and 3.97:1 -> 6.30:1
     light. One rule covers both themes because the variable is theme-dependent —
     a hex literal would fix one theme and move the other the wrong way. */
  .related-article-card:hover .related-article-arrow {
    transform: translateX(3px);
    color: var(--falcon-primary-text-emphasis) !important;
  }

  .related-article-card.related-article-card--warning:hover .related-article-arrow {
    color: var(--falcon-warning-text-emphasis) !important;
  }
}

/* Ratgeber link rows on the homepage Top-Ratgeber card and the guide card of every */
/* product page: icon-led article links that replace the former bullet list and reuse the */
/* related-articles hover language (sliding arrow, subtle row tint) so the section sits */
/* naturally in the Falcon design. */
.pd-ratgeber-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0.55rem;
  border-radius: var(--falcon-border-radius-lg);
  color: var(--falcon-gray-900);
}

/* Pin every icon to one fixed-width column so the link text starts at the same */
/* indent across all three columns. The fixed width is load-bearing: measured, the five */
/* icons in this list have five different intrinsic advances (12, 14, 16, 17 and 18 px), */
/* so without it the labels start at five different x positions. */
/* No !important: the earlier comment here claimed FontAwesome renders each glyph as an */
/* <svg class="svg-inline--fa"> whose own width rule had to be beaten. That was true of */
/* the SVG/JS delivery mode, which this project left on 19.08.2026 - it now loads the CSS */
/* plus webfont build, where svg.svg-inline--fa occurs 0 times in the DOM (measured) and */
/* nothing competes for width on this span. */
.pd-ratgeber-link__icon {
  width: 1.25rem;
  text-align: center;
  flex-shrink: 0;
}

/* The label between icon and arrow is a flex item, and a flex item's automatic minimum
   size keeps it from shrinking below its longest word. German compounds like
   "Kündigungsschutzklage" and "Standardformulierungen" therefore hold the row open, and
   the whole page scrolls sideways as soon as the type grows: measured on the homepage at
   375 px, the document overflowed by 10 px at a browser base font of 18 px and by 81 px
   at 24 px. min-width: 0 releases that floor and hyphens: auto lets the browser break the
   word properly instead of mid-syllable — the document is lang="de", so Chromium and
   Firefox apply real German hyphenation patterns. This is the same pair the
   .pd-overview-row rule further down this file already uses for the same reason. */
.pd-ratgeber-link > .flex-1 {
  min-width: 0;
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* The same pair for the product pages, where a German compound in a narrow column
   reached past the viewport at 320 px (design run of 10.10.2026). The class also sits on
   the page heading of includes/headline.html, which nearly every page of the site uses,
   blog and legal texts included. Cases measured: a product name in the
   overview list ("Arbeitszeugniserstellung" pushed its price 46 px out), the headline of
   a report's overall assessment, the title of a next step ("Arbeitsunfähigkeitsbescheini-
   gung einreichen" reached 27 px past the window), a date in the timeline and a section
   title of a form. Hyphenation is limited to the narrowest band: set on
   every width it split ordinary words ("Ter-min", "un-serer") at 375 and 1440 px too.
   The band ends at 380 px, measured as the first width from which "Scheinselbständigkeits-
   prüfung-Bericht" and "Aufhebungsvertragserstellung" fit; below it they broke mid-word
   without a hyphen. hyphenate-limit-chars keeps the band to long words: without it the
   overall assessment split "Schrei-ben" and "End-termin" at 360 px. Where an engine has no
   German patterns (WebKit in the measurement harness), `anywhere` is the fallback that
   keeps a long compound inside the viewport; unlike break-word it also lowers the
   element's min-content width. */
.pd-hyphenate {
  min-width: 0;
}

@media (max-width: 379.98px) {
  .pd-hyphenate {
    -webkit-hyphens: auto;
    hyphens: auto;
    hyphenate-limit-chars: 12 5 5;
    overflow-wrap: anywhere;
  }
}

/* The consent switches of the product forms: their labels measured 23.2 px high from
   768 px up, below the 24 px of WCAG 2.2 SC 2.5.8 (design run of 10.10.2026). */
.form-switch .form-check-label {
  line-height: 1.5rem;
}

.pd-ratgeber-arrow {
  margin-left: auto;
  flex-shrink: 0;
}

/* Focus stays ungated, as for .footer-link: a keyboard user on a touch device or with
   reduced motion keeps the row tint. */
.pd-ratgeber-link:focus-visible {
  background-color: var(--falcon-tertiary-bg);
}

/* Hover affordances are gated behind hover-capable pointers and motion preference */
/* so the tint and arrow slide never stick after a tap on touch devices (WCAG 2.3.3). */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .pd-ratgeber-link {
    transition: background-color var(--pd-transition-base);
  }

  .pd-ratgeber-link:hover {
    background-color: var(--falcon-tertiary-bg);
  }

  .pd-ratgeber-arrow {
    transition:
      transform var(--pd-transition-base),
      color var(--pd-transition-base);
  }

  .pd-ratgeber-link:hover .pd-ratgeber-arrow {
    transform: translateX(3px);
    color: var(--falcon-primary-text-emphasis) !important;
  }

  .pd-ratgeber-link--warning:hover .pd-ratgeber-arrow {
    color: var(--falcon-warning-text-emphasis) !important;
  }

  .pd-ratgeber-link--info:hover .pd-ratgeber-arrow {
    color: var(--falcon-info-text-emphasis) !important;
  }
}

/* Reporting improvement block: green-tinted highlight for AI-suggested rewrites and for
   the next step of a finding. */
.pd-improvement-block {
  margin-top: 0.75rem;
  padding: 0.75rem 0.875rem;
  background: rgba(var(--falcon-success-rgb), 0.08);
  border-left: 3px solid var(--falcon-success);
  border-radius: var(--falcon-border-radius-lg);
}

/* Slightly stronger green tint in dark mode so the success accent stays readable on a dark surface. */
[data-bs-theme="dark"] .pd-improvement-block {
  background: rgba(var(--falcon-success-rgb), 0.14);
}

/* Reporting hint block: subdued italic explanation under each improvement. */
.pd-hint-block {
  margin-top: 0.5rem;
  padding-left: 0.875rem;
  border-left: 2px dashed var(--falcon-gray-400);
  color: var(--falcon-gray-700);
  font-style: italic;
  font-size: 0.8333333333rem;
}

/* Footnote markers keep a floor, because their relative shrink compounds.
   The six <sup> in the project are the footnote pair of the three activation CTAs,
   and the browser's own 0.75em applies to whatever the parent already is: measured
   on the report page, the marker beside the comparison price renders at 10px and the
   one on the citation line at 8.33px, because that line is already fs-11 (11.11px).
   8.33px is not readable, and the marker is the only thing tying the 226,10 € claim
   to the § 34 RVG source that backs it — an unreadable pointer leaves a price
   comparison looking unsupported on the conversion path. `max()` keeps the relative
   behaviour wherever it still works and only puts a floor under it; support is
   Chrome 79+, Safari 11.1+, Firefox 75+, and a browser without it falls back to the
   inherited 0.75em, which is today's rendering. */
sup,
sub {
  font-size: max(0.75em, 11px);
}

/* Blog article body spacing. */
/* Templates use `mb-0` on every paragraph to keep <li><p> tight inside lists, */
/* which collapses standalone body paragraphs into a wall of text. These rules */
/* restore vertical rhythm on direct children of the article `.card-body` only — */
/* list items, includes, and non-article cards are unaffected. */
body.is-blog-article .card-body > p.fs-10 {
  margin-bottom: 1rem !important;
}

body.is-blog-article .card-body > h2 {
  margin-top: 2rem;
}

body.is-blog-article .card-body > h2:first-of-type {
  margin-top: 0;
}

body.is-blog-article .card-body > h3 {
  margin-top: 1.25rem;
  margin-bottom: 0.5rem;
}

body.is-blog-article .card-body > ul.fs-10,
body.is-blog-article .card-body > ol.fs-10 {
  margin-bottom: 1.25rem;
}

body.is-blog-article .card-body > ul.fs-10 li + li,
body.is-blog-article .card-body > ol.fs-10 li + li {
  margin-top: 0.4rem;
}

body.is-blog-article .card-body > .table-responsive {
  margin-top: 0.5rem;
  margin-bottom: 1.25rem;
}

body.is-blog-article .card-body > hr {
  margin-top: 1.25rem;
  margin-bottom: 1.25rem;
  opacity: 0.15;
}

/* Column widths for the three recurring article table shapes. They used to be 19 */
/* inline `style="width: N%"` attributes across three articles, in five different */
/* distributions for what are really three layouts: a grade table went 8/15/77 in one */
/* article, 10/20/70 in the next and 10/15/75 in the third. Nothing rendered wrong, */
/* but the proportions were re-invented per article and a change on narrow screens */
/* meant editing every attribute by hand. Declaring them once also settles which */
/* distribution is the right one. */
/* Note (grade) | rating | example formulation. The example column carries the long */
/* prose and gets the room; the grade column holds a single digit. */
.pd-table-grades th:nth-child(1) {
  width: 10%;
}

.pd-table-grades th:nth-child(2) {
  width: 20%;
}

.pd-table-grades th:nth-child(3) {
  width: 70%;
}

/* Note (grade) | satisfaction formula. */
.pd-table-formula th:nth-child(1) {
  width: 10%;
}

.pd-table-formula th:nth-child(2) {
  width: 90%;
}

/* Criterion | three comparable roles, each of which needs the same room. */
.pd-table-compare th:nth-child(1) {
  width: 19%;
}

.pd-table-compare th:nth-child(n + 2) {
  width: 27%;
}

/* No reading measure on the long form, by owner decision of 03.10.2026. Running
   text in blog articles and on the legal pages spans the full width of its card,
   like the tables and CTAs beside it. A `max-width: 68ch` on the copy of both
   surfaces (K19-i1-02) was removed that day: it left a wide empty strip to the
   right of every paragraph on desktop. Guarded by tests/test_long_form_full_width.py,
   so a later design or accessibility pass does not bring it back. */

/* Tabular figures in tables and in the large display size. Measured on the pillar
   article: all 18 numeric table cells rendered with proportional figures, so the price
   and grade columns of the comparison tables did not line up vertically — a 1 is
   narrower than a 4, and the decimal points drift across the rows. Figures outside
   tables use .pd-figures. This is a font feature, not a size or colour change: nothing
   reflows, because tabular figures are the same advance width the layout already
   reserves for the widest digit. */
td,
th {
  font-variant-numeric: tabular-nums;
}

/* Mobile horizontal-scroll affordance for wide (3+ column) article tables. */
/* initializeScrollableTables() in custom.js tags any overflowing .table-responsive with */
/* .pd-scrollable and inserts a .pd-table-hint label before it; without this cue the */
/* rightmost column is silently clipped on phones. The right-edge mask fades the content so */
/* the clipping reads as "more to the right", and lifts once the user scrolls to the end. */
/* --falcon-gray-700, not -600: at 12px the 600 tone measures 3.95:1 against the card, */
/* below the 4.5:1 of WCAG 2.2 AA (1.4.3), and this label is the only cue that the */
/* rightmost table column is clipped. It is the same substitution .form-text already */
/* makes for the same reason. */
.pd-table-hint {
  display: none;
  margin-bottom: 0.35rem;
  font-size: 0.75rem;
  color: var(--falcon-gray-700, #5e6e82);
  text-align: right;
}

@media (max-width: 575.98px) {
  .pd-table-hint:has(+ .table-responsive.pd-scrollable) {
    display: block;
  }

  .table-responsive.pd-scrollable:not(.pd-scroll-end) {
    -webkit-mask-image: linear-gradient(to right, #000 86%, transparent 100%);
    mask-image: linear-gradient(to right, #000 86%, transparent 100%);
  }
}

/* Sticky bottom CTA bar shown on paid product reporting pages until activation. */
/* Positioning, theme-aware background (var(--falcon-tertiary-bg)) and top border come from */
/* the Bootstrap/Falcon utilities .fixed-bottom .bg-body-tertiary .border-top on the element. */
/* Only the upward shadow and iOS safe-area inset stay here — neither has a utility class. */
.pd-sticky-cta {
  box-shadow: var(--pd-shadow-sticky);
  padding-bottom: env(safe-area-inset-bottom);
}

/* Stronger upward shadow in dark mode to keep the sticky bar visually separated from the dark page. */
[data-bs-theme="dark"] .pd-sticky-cta {
  box-shadow: var(--pd-shadow-sticky-dark);
}

/* Reserve room at the bottom of the main content so the sticky bar never covers the last card. */
/* 9rem matches the bar below 992 px, whose guarantee line also carries the AGB and privacy */
/* links: measured on the locked reports of 10.10.2026 (design run) it is 139 px from 320 */
/* to about 420 px, where the guarantee line wraps, 91 px from 430 px up, and 92 to 122 px */
/* between 768 and 991 px, where the price and button group squeezes the guarantee line; */
/* the earlier 7.5rem left 19 px of the last card covered, and a 4.5rem reserve from 768 px */
/* left the footer's brand link under the bar. From 992 px the "Einmalzahlung" line no */
/* longer wraps and the bar measures 57 px. */
body:has(.pd-sticky-cta) .content {
  --pd-content-pad-bottom: 9rem;
}

@media (min-width: 992px) {
  body:has(.pd-sticky-cta) .content {
    --pd-content-pad-bottom: 4.5rem;
  }
}

/* At exactly 320 px the form pages' sticky bar gains one more line and outgrows the
   space reserved for it, so the last content card stays covered no matter how far the
   visitor scrolls. Measured across 320-768 px: .sticky-cta-bar is 61 px from 340 px
   upwards but 85 px at 320 px (reserve 72 px), because the label of its one button (a
   link that jumps to the form) wraps to a second line. Raising the reserve by one line
   height in that band is the smaller change than shortening every product's label. The purchase bar of
   the locked reports needs no entry here: its 9rem reserve above already covers its
   139 px at 320 px. The 340 px boundary is the one the theme-toggle rule further down
   this file already uses. */
@media (max-width: 339.98px) {
  body:has(.sticky-cta-bar) .content {
    --pd-content-pad-bottom: 6rem;
  }
}

/* Up to 450 px of height (a phone in landscape, 400 % zoom) the bars stay in the page
   flow: fixed, the purchase bar and the sticky header left 48 px of a 320 x 256 window
   for the report (WCAG 2.2 SC 1.4.10). The button remains on the page, and the
   activation card carries the same purchase. */
@media (max-height: 450px) {
  .pd-sticky-cta.fixed-bottom,
  .sticky-cta-bar,
  [data-bs-theme="dark"] .sticky-cta-bar {
    position: static;
    box-shadow: none;
  }

  body:has(.pd-sticky-cta) .content,
  body:has(.sticky-cta-bar) .content {
    --pd-content-pad-bottom: 0;
  }
}

/* Links inside running text were marked by colour alone. Measured: the link blue
   (#2c7be5) against the body ink (#344050) is 2.54:1, where WCAG 2.2 SC 1.4.1 (A) wants
   either 3:1 plus a non-colour cue on hover and focus, or a permanent non-colour cue.
   axe counted 148 such links in light mode across 21 surfaces — the three pillar articles
   alone hold 112 — and they include the consent links to the AGB and the privacy policy
   on the forms, which a reader has to be able to find.
   The rule is deliberately narrow: only anchors inside a paragraph or list item of a card
   body, never buttons, badges, cards or navigation, all of which carry their own shape.
   Verified against the rendered pages of the blog, the legal texts, a report and the
   homepage — 0 of 99 matched anchors were a styled control. The offset keeps the rule
   clear of descenders in Open Sans. */
.card-body p a:not(.btn):not([class*="badge"]),
.card-body li a:not(.btn):not([class*="badge"]),
.card-body h2 a:not(.btn),
.card-body h3 a:not(.btn),
.form-check-label a:not(.btn) {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* Focus indicator reinforcement (WCAG 2.4.7). */
/* Falcon and Bootstrap occasionally remove the native outline on buttons/links. */
/* :focus-visible only triggers for keyboard users — mouse clicks remain visually clean. */
/* One ring, drawn as an outline with a 2px offset. An earlier version of this comment */
/* promised a double ring of box-shadow plus outline; there is no box-shadow here, and */
/* the rule below this one deliberately clears any that Falcon leaves behind. The offset */
/* is what separates the ring from the control, so a second ring buys nothing. */
:focus-visible {
  outline: 2px solid var(--falcon-primary);
  outline-offset: 2px;
}

/* The bare :focus-visible rule above (specificity 0,1,0) loses to Falcon's own */
/* .nav-link:focus-visible{outline:0} (0,2,0) and .navbar .nav-link:focus-visible */
/* {box-shadow:none} (0,3,0) in theme.min.css, so every link in the vertical */
/* navigation and the top navbar was measurably focus-invisible — 11 consecutive */
/* tab stops on every page, directly after the skip link. Matching the higher */
/* specificity is the whole point of this rule; do not "simplify" it back into the */
/* selector above. Verify with getComputedStyle after a real Tab keypress, not after */
/* element.focus() — :focus-visible does not necessarily match on programmatic focus. */
/* .btn is in the same list for the same reason: Falcon's .btn:focus-visible{outline:0} */
/* (0,2,0) also beats the bare rule. Buttons were not invisible — the outline-* */
/* variants invert their colours on focus — but that state is identical to hover, so */
/* a keyboard user could not tell focus from a hovered button, and it departed from */
/* the 2px outline used everywhere else. */
.navbar .nav-link:focus-visible,
.navbar-vertical .nav-link:focus-visible,
.nav-link:focus-visible,
.btn:focus-visible {
  outline: 2px solid var(--falcon-primary);
  outline-offset: 2px;
  box-shadow: none;
}

/* The form controls were missing from the list above, for the same reason and with a
   worse outcome: .form-control:focus and .form-select:focus set outline: 0 (0,2,0) and
   beat the bare :focus-visible rule, and the box-shadow Bootstrap normally puts in its
   place resolves here to a fully transparent ring — measured on every field of every
   form, in all three engines, as `outline: 0px none` plus
   `rgba(0, 0, 0, 0) 0px 0px 0px 0px`, with the resting border colour unchanged. The
   result was a form whose focus was invisible from the first field on: the upload
   control of the two analysis products, every text field of the Arbeitszeugniserstellung
   and both consent switches (WCAG 2.2 SC 2.4.7, AA). Verified with real Tab presses, not
   element.focus() — :focus-visible does not necessarily match on programmatic focus. */
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible {
  outline: 2px solid var(--falcon-primary);
  outline-offset: 2px;
}

/* Contrast repair for two Falcon defaults that fail WCAG 1.4.3 (AA) at 4.5:1. */
/* Both use --falcon-gray-500 (#9da9bb), which measures 2.38:1 on white, 2.12:1 on the */
/* page background and 2.28:1 on the legal pages' card. Neither is decoration: */
/* .form-text carries the upload limits and the salary bounds — exactly the rules whose */
/* violation produces the upload error — and the legal sidebar entries are links. */
/* --falcon-gray-700 (#5e6e82) measures 5.21:1 on white, 4.99:1 on the legal pages' */
/* card and 4.63:1 on the page background — above AA in every context where these two */
/* selectors actually render. This is a local override, not a change to the palette. */
.form-text,
.terms-sidebar .nav-link {
  color: var(--falcon-gray-700);
}

/* The floating labels were the third place the same grey slips below AA, and the one
   that matters most: the label IS the field's name, and while the field is empty it is
   the only thing that says what belongs in it. Falcon fades --falcon-gray-700 to 65 %
   opacity, which composites to #96a1ae on the white card — measured 2.63:1 in light mode
   and 3.77-3.90:1 on the two dark surfaces, against the 4.5:1 of WCAG 2.2 SC 1.4.3 (AA).
   Full opacity is the smallest step that clears it in light mode (0.94 would be enough,
   but a value that close to 1 buys nothing) and lifts the dark surfaces to 7.06-7.57:1.
   The grey itself is unchanged; only the veil over it is removed. */
.form-floating > label {
  opacity: 1;
  color: var(--falcon-gray-700);
}

/* Skip link must rise above the sticky CTA (z-index 1030) when focused so keyboard users */
/* can always escape to the main content. Falcon's .visually-hidden-focusable handles */
/* hide/reveal; we only need to bump stacking. :focus-within covers the case where the */
/* anchor itself is not the focus target but a descendant is (defensive double-binding). */
/* The 1090 value intentionally sits just above Bootstrap's tooltip layer (1080) — */
/* a tooltip must never obscure the only keyboard escape route to the main content. */
.visually-hidden-focusable:focus,
.visually-hidden-focusable:focus-within {
  z-index: 1090;
}

/* Forced colors / Windows High Contrast Mode (WCAG 1.4.11). */
/* Strip decorative gradients and shadows so system colours can repaint affordances cleanly. */
/* Pulse animations are suppressed because the animated box-shadow conveys nothing without */
/* color (forced-colors removes shadows anyway, leaving only a meaningless scale tick). */
@media (forced-colors: active) {
  .pulse,
  .pulse-info {
    animation: none !important;
  }

  /* .pd-improvement-block used to be listed here too. It sets no box-shadow
     anywhere in this file, so the declaration neutralised nothing.
     Counted, this file sets a real box-shadow in twelve places: the two
     .demo-image-hover-* hovers, .sticky-cta-bar and its dark twin,
     .related-article-card:hover/:focus-within and its dark twin, .pd-sticky-cta
     and its dark twin, the two .form-range:focus-visible thumb rules, the sheet
     .pd-paper and the deadline ring of the timeline, which gets an outline below.
     Only .pd-sticky-cta is cleared here, and the reason is that its shadow is the
     one that would otherwise be redrawn as a solid system colour and read as a
     second border above the .border-top the include already carries. The deadline
     ring carries meaning and is replaced by the outline below; the seven decorative
     ones need no rule - forced-colors drops them by itself. The two
     .form-range thumb rules must NOT be added: they are the focus indicator of the
     three rating sliders, the one place where outline cannot be used (see their own
     comment), and clearing them would take the focus ring off the controls that
     decide the grades of a purchased certificate. */
  .pd-sticky-cta {
    box-shadow: none !important;
  }

  /* The scale and the bars draw their meaning with background colours, which forced
     colours removes; a system-colour border keeps their extent, and the bar's value and
     the scale's marker are painted in the system text colour. */
  .pd-scale {
    border: 1px solid CanvasText;
  }

  /* The bar is drawn by hand here: forced colours painted track and value alike in
     Canvas, and the base rule's border: 0 further down this file beat a plain .pd-bar
     selector, so the bars vanished entirely (design run of 10.10.2026). The element
     selector outranks it. */
  progress.pd-bar {
    forced-color-adjust: none;
    background-color: Canvas;
    border: 1px solid CanvasText;
  }

  progress.pd-bar::-webkit-progress-bar {
    background-color: Canvas;
  }

  progress.pd-bar::-webkit-progress-value {
    background-color: CanvasText;
  }

  progress.pd-bar::-moz-progress-bar {
    background-color: CanvasText;
  }

  /* Scoped under .pd-scale: the base rule further down this file sets the marker's
     colour at one class and would win by order. */
  .pd-scale .pd-scale__marker {
    forced-color-adjust: none;
    background-color: CanvasText;
  }

  /* A ticked switch draws its state with its fill, which forced colours removed: on
     Canvas the white knob vanished and the two consent switches showed an empty frame
     when ticked. The system highlight carries the fill back. */
  .form-switch .form-check-input:checked {
    forced-color-adjust: none;
    background-color: Highlight;
    border-color: Highlight;
  }

  /* The ring marks the deadline among the dates; forced colours drop the shadow. */
  .pd-timeline__item--deadline .pd-timeline__dot {
    outline: 2px solid CanvasText;
    outline-offset: 1px;
  }

  .demo-video-primary,
  .demo-video-warning {
    background: Canvas !important;
  }

  :focus-visible {
    outline: 2px solid CanvasText;
  }
}

/* Print stylesheet for reports and blog articles. */
/* Users frequently print/save-as-PDF analysis reports for HR meetings or labour court */
/* filings — hide all interactive chrome (navbar, sticky CTA, footer, related articles) */
/* so the printed page contains only the substantive content. */
@media print {
  .navbar-top,
  .navbar-vertical,
  .footer,
  .pd-sticky-cta,
  .sticky-cta-bar,
  .related-articles,
  .pulse,
  .pulse-info,
  .visually-hidden-focusable,
  #cc-main {
    display: none !important;
  }

  body,
  .content,
  .content > main,
  .card,
  .card-body {
    background: #ffffff !important;
    box-shadow: none !important;
    color: #000000 !important;
  }

  a {
    color: #000000 !important;
    text-decoration: underline;
  }

  /* Avoid orphan headings on page breaks. */
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    page-break-after: avoid;
    break-after: avoid;
  }

  /* Keep tables and lists together where possible. */
  table,
  ul,
  ol {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  /* A card stretched to its row (h-100) kept the row's height when it moved to a new
     page and hid the end of its list under the next card; the number tiles, a bar with
     its label and a card head with nothing below it were cut across a page break
     (design run of 10.10.2026). The grid of the warning checks may break between its
     tiles, each tile stays whole. */
  .card.h-100 {
    height: auto !important;
  }

  .card-header {
    break-after: avoid;
  }

  .card-body > .row.g-2:not(:has(.pd-check-tile)),
  .card-body > div:has(> .pd-bar),
  .pd-check-tile {
    break-inside: avoid;
  }

  .card-body > .d-flex:has(+ .pd-bar) {
    break-after: avoid;
  }

  /* Each critical passage of the two original analyses stays whole; the card itself may
     break, so a long list does not leave the rest of a page empty above it. A card with a
     single passage stays whole, or its top edge stood alone at the foot of a page. */
  .card.border-danger .card-body > .border-danger,
  .card.border-danger:has(.card-body > .border-danger):not(
      :has(.card-body > .border-danger ~ .border-danger)
    ) {
    break-inside: avoid;
  }

  /* The findings start on a page of their own: their head and the AI note stood alone
     at the foot of a page with the first finding on the next (design run of
     10.10.2026), and no break-after held in Chromium, which split the two-line note
     instead. */
  .pd-findings {
    break-before: page;
  }

  .pd-paper__heading {
    break-after: avoid;
  }

  /* A letter's list may run across a page; the rule above for ul and ol would push a
     long one whole onto the next page. Its items stay whole. */
  .pd-paper__list {
    break-inside: auto;
  }

  .pd-paper__list > li {
    break-inside: avoid;
  }

  /* The next steps may run across a page, each step too; only a step's title stays with
     its text. A whole first step (124 px) did not fit at the foot of page 1, took the
     card head with it, and the block below then lost its last line to a page of its
     own (payslip report, design run of 10.10.2026). */
  .pd-steps {
    break-inside: auto;
  }

  .pd-steps__item > :first-child {
    break-after: avoid;
  }

  /* The document card starts on a page of its own, as the findings do: its title and AI
     note stood alone at the foot of a page, the letter on the next. */
  .card:has(> .card-body > .pd-paper:not(.pd-paper--preview)) {
    break-before: page;
  }

  .card:has(> .card-body > .pd-paper--preview) {
    break-inside: avoid;
  }

  .pd-paper--preview::after {
    display: none;
  }

  /* A finding may run across a page, its quote, wording and core sentence may not: kept
     whole, a finding of most of a page pushed the first one under "Prüfpunkte im
     Einzelnen" onto the next page and left the head alone on an empty one. The three
     parts (dd) may break between lines, at least two on either side: kept whole as
     well, they left up to 78 mm of a card empty above a part that would have fit. */
  .pd-quote,
  .pd-wording,
  .pd-finding > p {
    break-inside: avoid;
  }

  .pd-finding__parts > dd {
    orphans: 2;
    widows: 2;
  }

  .pd-finding__parts > dt,
  .pd-finding > p:has(+ .pd-quote),
  .pd-finding > p:has(+ .pd-finding__parts) {
    break-after: avoid;
  }

  /* Badges, step numbers, bars and the scale carry their meaning in a fill; printed
     without background graphics, the white badge text and step numbers vanished and
     the bars came out empty (design run of 10.10.2026). The icon tiles are listed for
     the same reason: a white glyph printed light grey on white (2.30:1). */
  .badge,
  .icon-item,
  .pd-steps__item::before,
  .pd-bar,
  .pd-scale,
  .pd-scale__marker,
  .pd-timeline__dot {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Print improvement/hint side-bar blocks as plain readable paragraphs
       without the colored borders/backgrounds that confuse on paper. */
  .pd-improvement-block,
  .pd-hint-block {
    background: transparent !important;
    border-left: none !important;
    color: #000000 !important;
    padding-left: 0 !important;
  }
}

/* Compact top-nav product CTAs (Analysen / Erstellungen). Slimmer than a default
   button so the bar stays light: reduced vertical padding and a 34 px min-height
   that still satisfies the WCAG 2.5.8 (AA) 24 px target. On phones the labels are
   hidden (icon only), so the horizontal padding is tightened further. */
.pd-nav-cta {
  min-height: 34px;
  padding-top: 0.2rem;
  padding-bottom: 0.2rem;
}

@media (max-width: 575.98px) {
  .pd-nav-cta {
    min-height: 32px;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }
}

/* The two product menus list the whole portfolio (09.10.2026), up to fourteen entries
   with their topic headers. Capped below the viewport height and scrolled inside, so
   the last entries stay reachable on a short laptop screen or a phone in landscape.
   Scoped under .navbar because the theme's `.navbar .dropdown-menu { overflow: visible }`
   otherwise wins on specificity and the entries spill out of the menu. */
.navbar .pd-nav-menu {
  max-height: 75vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* The product names in both menus start on one edge whatever the width of their icon,
   as in the product lists (fa-fw there; the menu entries live in includes/top.html). */
.pd-nav-menu .dropdown-item > .fas {
  width: 1.25em;
  text-align: center;
}

/* Below the sm breakpoint the "Analysen" menu, aligned to the end of its button, opened
   42 px past the left edge at 320 px and 28 px at 360 px, cutting off icons and topic
   headings (design run of 10.10.2026). In that range both menus span the window instead.
   The !important is required: Popper writes position, inset and transform as inline
   styles on the open menu. */
@media (max-width: 575.98px) {
  .navbar .pd-nav-menu.show {
    position: fixed !important;
    inset: 4rem 0.5rem auto 0.5rem !important;
    transform: none !important;
  }

}

/* A fixed bar at the bottom (the purchase bar of a locked report, 139 px at 320 px, or
   the bar of a form below 992 px, whose button jumps to the form) lies above the menus and covered their last
   entries, on phones upright and in landscape. Each menu stops short of the bar's
   reserve plus the 4rem the menu opens below; vh is the fallback for engines without
   dvh, which follows Safari's toolbar. */
body:has(.pd-sticky-cta) .navbar .pd-nav-menu.show {
  max-height: min(75vh, calc(100vh - 13rem));
  max-height: min(75dvh, calc(100dvh - 13rem));
}

@media (min-width: 992px) {
  body:has(.pd-sticky-cta) .navbar .pd-nav-menu.show {
    max-height: min(75vh, calc(100vh - 8.5rem));
    max-height: min(75dvh, calc(100dvh - 8.5rem));
  }
}

@media (max-width: 991.98px) {
  body:has(.sticky-cta-bar) .navbar .pd-nav-menu.show {
    max-height: min(75vh, calc(100vh - 10rem));
    max-height: min(75dvh, calc(100dvh - 10rem));
  }
}

/* D17-S3-001, D33-S3-001, D26-S4-001 of the design run: the vertical navigation ends at
   the bottom of the window, so a fixed bar covered its last links (Impressum, the whole
   group "Rechtlich" on a locked report), both in the menu behind the hamburger and in
   the sidebar from 1200 px, where tabbing put Blog and Impressum under the bar (WCAG 2.2
   SC 2.4.11). A scroll padding did not help: the container itself reached under the bar
   and had nothing to scroll. It now ends above the bar's reserve and scrolls inside. The
   !important answers the theme's own for the card navigation (.navbar-card, max-height
   with !important), which otherwise wins whatever the specificity. */
body:has(.pd-sticky-cta) .navbar-vertical .navbar-collapse .navbar-vertical-content {
  max-height: calc(100vh - var(--falcon-top-nav-height) - 9rem) !important;
  max-height: calc(100dvh - var(--falcon-top-nav-height) - 9rem) !important;
}

@media (min-width: 992px) {
  body:has(.pd-sticky-cta) .navbar-vertical .navbar-collapse .navbar-vertical-content {
    max-height: calc(100vh - var(--falcon-top-nav-height) - 4.5rem) !important;
    max-height: calc(100dvh - var(--falcon-top-nav-height) - 4.5rem) !important;
  }
}

@media (max-width: 991.98px) {
  body:has(.sticky-cta-bar) .navbar-vertical .navbar-collapse .navbar-vertical-content {
    max-height: calc(100vh - var(--falcon-top-nav-height) - 6rem) !important;
    max-height: calc(100dvh - var(--falcon-top-nav-height) - 6rem) !important;
  }
}

/* Up to 450 px of height the bars stand in the page flow (the rule "Up to 450 px of
   height" above), so the menus and the scroll position keep no room for them: at
   320 x 256 the reserves left both menus 43 to 48 px high. This sits after the menu
   rules because it has to win against them. */
@media (max-height: 450px) {
  html:has(.sticky-cta-bar),
  html:has(.pd-sticky-cta) {
    scroll-padding-bottom: 0;
  }

  body:has(.pd-sticky-cta) .navbar .pd-nav-menu.show,
  body:has(.sticky-cta-bar) .navbar .pd-nav-menu.show {
    max-height: 75vh;
    max-height: 75dvh;
  }

  body:has(.pd-sticky-cta) .navbar-vertical .navbar-collapse .navbar-vertical-content,
  body:has(.sticky-cta-bar) .navbar-vertical .navbar-collapse .navbar-vertical-content {
    max-height: calc(100vh - var(--falcon-top-nav-height) - 1rem) !important;
    max-height: calc(100dvh - var(--falcon-top-nav-height) - 1rem) !important;
  }
}

/* The menu behind the hamburger scrolled the page behind it once it reached its end. */
.navbar-vertical .navbar-vertical-content {
  overscroll-behavior: contain;
}

/* Theme toggle in the top navbar sized to the 44 px AAA touch target (WCAG 2.5.5) on every */
/* width outside the two narrow bands below. */
.pd-theme-toggle {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* The Falcon theme hides the toggle's checkbox with display: none and paints the */
/* two icon labels instead. display: none also removes the element from the tab */
/* order and from the accessibility tree, which left the light/dark switch usable */
/* by pointer only — it did not exist for keyboard or screen reader users at all */
/* (WCAG 2.1.1 Level A, 4.1.2 Level A). Hiding it visually instead keeps it */
/* focusable and operable with Space, while the icon labels keep rendering the */
/* visual state. The 1 px box plus pointer-events: none prevents it from */
/* intercepting clicks meant for the labels. */
.pd-theme-toggle .theme-control-toggle-input {
  display: block;
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

/* Keyboard focus lands on the invisible checkbox, so the ring has to be drawn on */
/* the visible labels next to it. */
.pd-theme-toggle .theme-control-toggle-input:focus-visible ~ .theme-control-toggle-label {
  outline: 2px solid var(--falcon-primary);
  outline-offset: 2px;
  border-radius: var(--falcon-border-radius-sm);
}

/* The Falcon table tokens are defined once without a dark-mode counterpart, so */
/* table cells kept the light-mode ink (#5e6e82) on the dark card background — */
/* measured at 3.22:1, below the 4.5:1 AA floor, while the surrounding body copy */
/* correctly remaps to #9da9bb. This affects every comparison table in the blog */
/* and the sentence table of the paid report. Both tokens are needed: striped */
/* rows resolve their colour through --falcon-table-striped-color, so remapping */
/* only the base token would leave every second row failing (measured: 38 of 90 */
/* cells still at 3.22:1). */
[data-bs-theme="dark"] table {
  --falcon-table-color: var(--falcon-body-color);
  --falcon-table-striped-color: var(--falcon-body-color);
}

/* The navigation row (hamburger + logo + two dropdowns + theme toggle) overshoots the */
/* viewport in two narrow bands. Measured with both size rules forced on and off across */
/* 320-768 px, the row needs the reduced toggle below 340 px and again between */
/* 576 px and 620 px, where Bootstrap's sm breakpoint widens me-sm-3 and reveals the */
/* dropdown labels. Everywhere else — including every common phone width from 360 px */
/* up — the toggle keeps its 44x44 px WCAG 2.5.5 (AAA) target. The two bands must be */
/* read together with the logo rule below: neither alone clears 320 px. */
/* The upper bound is 339.98px, not 340px: re-measured on 16.09.2026 with the rule */
/* forced off, the row overshoots by 6 px at 320 px and by 10 px at 576 px but by 0 px */
/* at 339, 340 and 341 px, so at exactly 340 px the toggle can keep its full target. */
/* That also closes a one-pixel disagreement: the form bar's reserve above breaks */
/* at 339.98px, so at 340px the control used to shrink while the space reserved for the */
/* bar did not. The responsive matrix measures 320 and 375 and never saw it. */
@media (max-width: 339.98px), (min-width: 576px) and (max-width: 620px) {
  .pd-theme-toggle {
    min-width: 30px;
    min-height: 32px;
  }
}

/* Below 375 px the 180 px logo leaves too little room for the rest of the navigation */
/* row: measured overflow is 52 px at 320 px, 32 px at 340 px and 12 px at 360 px with */
/* the toggle at full size. Scaling the logo reclaims exactly that, and the aspect */
/* ratio is preserved (180/36 = 130/26 = 5) so no layout shift is introduced. The bound */
/* is 374.98 px rather than 356 px because at 360 px the reduced toggle alone no longer */
/* applies — the two rules cover overlapping, not identical, ranges. */
@media (max-width: 374.98px) {
  .navbar-top .navbar-brand img {
    width: 130px;
    height: auto;
  }
}

/* The hamburger's 24 px floor above costs the row four pixels, and in two narrow bands
   the row has none to give: measured with the floor in place and the brand held at its
   documented width, the page overflowed by 1 px at 375 px and by 4 px at 576 px, while
   320 px, 600 px and 620 px still fit. Those four pixels are taken from the wordmark
   rather than from a control, and by a fixed amount rather than by letting flexbox
   decide — with `min-width: 0; flex-shrink: 1` on the brand the algorithm overshot to
   153 px at 375 px and 136 px at 600 px, a visible 15-24 % shrink of the logo at the
   default font size, which contradicts the two widths the project deliberately picked
   (180 px, and 130 px below 375 px). 172 px keeps eight pixels of headroom and is a
   4 % step, which is not perceptible beside the 28 % step the 130 px rule already makes.
   `min-height` guards the link's own hit area at the 24 px of WCAG 2.2 SC 2.5.8 (AA).
   The image deliberately carries no `max-width: 100%`: that declaration removes the
   flex item's automatic minimum size, and the wordmark then shrank on its own at every
   tight width — measured 112 px at 320 px, 152 px at 375 px and 124 px at 640 px, none
   of which any rule asked for. Its width stays under the explicit control of the two
   band rules instead. */
.navbar-top .navbar-brand {
  min-height: 24px;
}

@media (min-width: 375px) and (max-width: 430px), (min-width: 576px) and (max-width: 620px) {
  .navbar-top .navbar-brand img {
    width: 172px;
  }
}

/* Stop spinning animations for users who prefer reduced motion (WCAG 2.3.3). */
/* FontAwesome's .fa-spin runs as a CSS animation; on long-running pages like the */
/* thanks page countdown (up to 60s), the endless rotation can trigger vestibular */
/* discomfort. Suppressing it leaves the cog icon visible but stationary, which */
/* still communicates "in progress" alongside the live-region countdown text. */
@media (prefers-reduced-motion: reduce) {
  .fa-spin {
    animation: none !important;
  }

  /* The vendored theme animates the sidebar's width and labels, the hamburger lines,
     the theme toggle and the icon tiles without asking; the header's promise covers
     them only with this rule. */
  .navbar-vertical,
  .navbar-vertical *,
  .navbar-vertical *::before,
  .navbar-vertical *::after,
  .navbar-toggle-icon,
  .navbar-toggle-icon::before,
  .navbar-toggle-icon::after,
  .navbar-toggle-icon *,
  .navbar-toggle-icon *::before,
  .navbar-toggle-icon *::after,
  .toggle-line,
  .theme-control-toggle-label,
  .icon-item {
    transition: none !important;
  }
}

/* Legal pages: improved vertical rhythm for long-form text on mobile. */
/* Mirrors the body.is-blog-article pattern but with tighter spacing for legal text. */
/* Long paragraphs and ordered lists in tos.html and privacy.html otherwise render */
/* as walls of text on narrow viewports because every <p> uses mb-0 by convention. */
body.is-legal-page .card-body > p.fs-10 + p.fs-10 {
  margin-top: 0.75rem;
}

body.is-legal-page .card-body > h3 {
  margin-top: 1.5rem;
}

body.is-legal-page .card-body > ul.fs-10,
body.is-legal-page .card-body > ol.fs-10 {
  margin-bottom: 1rem;
}

body.is-legal-page .card-body > hr {
  margin-top: 1rem;
  margin-bottom: 1rem;
  opacity: 0.15;
}

/* Stats cards on home.html: reduce minimum width so two columns fit comfortably on */
/* phones (375px viewport / 2 columns = ~180px effective width). The previous 12rem */
/* (192px) caused horizontal overflow on the smallest supported viewport. */
.pd-stat-card-min {
  min-width: 10rem;
}

/* Links inside a table cell are the same defect as the article titles below, and
   they were reported twice before without being fixed: the internal cross-links in
   the comparison tables of the articles (329 tables) and the unlock links in the
   rating tables of the two analysis reports. Measured at 18 px high, and where the
   link is the whole content of its cell - which it is in these tables, the cell text
   and the link text are the same length - the inline exception of WCAG 2.2 SC 2.5.8
   (AA) does not cover it.
   The same mechanism as below: vertical padding on an inline element grows its hit
   box without growing its line box. Verified across three surfaces at 375 and
   1440 px that row heights, table heights and page height are byte-identical before
   and after, so the rule may match generously - a cell that holds text AND a link
   is unaffected either way, which is why CSS does not need to express "sole content
   of the cell" here. Minimum height 18 -> 26 px, count below 24 px: 18 -> 0. */
.card-body .table td a:not(.btn),
.card-body .table th a:not(.btn) {
  padding: 0.25rem 0;
}

/* The article title is the primary navigation target of the three category
   overviews, 140 rows in all, and it is the only content of its <h2> — so the
   inline exception of WCAG 2.2 SC 2.5.8 (AA) does not apply to it. Measured at
   375 and 1440 px it renders 23.0 px high: the inline box follows Open Sans's own
   ascent-plus-descent (1.4375 em at 16 px), which is why raising the h2's
   line-height would not move it. Vertical padding on the inline anchor lifts it to
   31 px and moves nothing else, because padding on an inline element does not grow
   its line box and the anchor carries no background. This mirrors what
   .footer-brand above does for the identical defect, with the same 0.25rem.
   Titles that wrap to two lines already measured 42 px and are unaffected. */
.pd-overview-row > h2 > a {
  padding: 0.25rem 0;
}

/* The icon column of each article row. This was an inline style repeated verbatim in
   all three overview templates, inside the article loop — 70 + 42 + 28 attributes,
   140 of the 146 inline styles measured across the whole site, and a width to change
   in three places. The parent already carried .pd-overview-row, so the class was the
   only thing missing. */
.pd-overview-row > .pd-overview-icon {
  width: 32px;
  text-align: center;
}

/* Below the sm breakpoint the article rows in the category overviews cannot hold title
   and category badge side by side: at 320 px the title column measures ~106 px, less
   than a single long word, and the badge was pushed 51 px past the viewport. Letting
   the row wrap moves the badge under the title and gives the title the full line;
   min-width: 0 additionally allows the column to shrink below its min-content width,
   and hyphens: auto prefers proper German hyphenation over a mid-word break (the
   document is lang="de", so Chromium and Firefox apply real hyphenation patterns).

   All three declarations are scoped to this range on purpose. Applied unconditionally,
   min-width: 0 also shrank the two-column layout at 768-900 px, where the row fits at
   full width — it introduced word breaks there instead of preventing them. */
@media (max-width: 575.98px) {
  .pd-overview-row {
    flex-wrap: wrap;
  }

  .pd-overview-row > h2.flex-grow-1 {
    min-width: 0;
    flex-basis: 100%;
    -webkit-hyphens: auto;
    hyphens: auto;
  }
}

/* At 320 px a col-6 is only ~146 px wide, so the 10rem (160 px) floor pushed the two
   stat cards 8 px past the viewport and produced the last remaining horizontal scroll
   bar on the site. Below 400 px the column width is the sensible constraint; the cards
   stay readable because their text is already set at the small fs-9 scale. */
@media (max-width: 400px) {
  .pd-stat-card-min {
    min-width: 0;
  }
}

/* Circular icon tiles on the blog overview, the home product cards, the related-  */
/* articles cards and the thanks page. Three fixed sizes, previously repeated as    */
/* nine inline width/height pairs. Falcon's own .icon-item scale does not carry     */
/* these values (sm 30px, lg 44px, xl 50px), so pulling them onto it would resize   */
/* every tile visibly for no stated reason — the values stay, only the inline style */
/* goes. Named after the pixel size like .pd-card-min-12 names its rem floor.       */
.pd-icon-tile-40,
.pd-icon-tile-56,
.pd-icon-tile-64 {
  flex-shrink: 0;
}

.pd-icon-tile-40 {
  width: 40px;
  height: 40px;
}

.pd-icon-tile-56 {
  width: 56px;
  height: 56px;
}

.pd-icon-tile-64 {
  width: 64px;
  height: 64px;
}

/* Corner-illustration cards in the steps, privacy and reporting section blocks. The */
/* 12rem floor keeps the illustration from crowding the text; these cards are never  */
/* narrower than a full column on phones, so unlike .pd-stat-card-min they do not    */
/* need the reduced 10rem width. Declared once here instead of twelve inline styles. */
.pd-card-min-12 {
  min-width: 12rem;
}

/* WebKit propagates a <select>'s layout overflow to its ancestors: the closed control
   is laid out at its own width (303 px here) but the widest <option> — "10 oder weniger
   Mitarbeiter (Teilzeit anteilig)" on the Kündigungsanalyse form — still contributes to
   the scrollable area, which travels up through .form-floating, .card-body and .content
   until the document itself scrolls. Measured on the JTA form: 14 px of horizontal page
   scroll at 320 px and 29 px at 375 px in WebKit, 0 px in Chromium and Gecko, confirmed
   with a real window.scrollTo(400, 0) reporting scrollX = 29. Since every browser on iOS
   uses WebKit, that is every iPhone visitor of that form.
   Clipping the select itself is the narrowest fix that works: overflow never affects an
   element's own outline, so the focus ring stays intact, and the dropdown popup is drawn
   by the operating system and is likewise unaffected. Applying the same clip one level up
   on .form-floating also removes the overflow but would clip the focus ring of the field
   inside it, trading a layout defect for a WCAG 2.4.7 defect. */
select.form-select {
  overflow: hidden;
}

/* Badges on the light brand fills carry dark text instead of white. White on        */
/* --falcon-success (#00d27a) measures 2.0:1, on --falcon-info (#27bcfd) 2.17:1 and  */
/* on --falcon-warning (#f5803e) 2.61:1 — all far below the 4.5:1 that WCAG 2.2 SC   */
/* 1.4.3 (AA) requires, and none of them reaches the large-text exemption at the     */
/* badge font size. These are not decorative: they carry the grade legend of the paid*/
/* Arbeitszeugnisanalyse report and the Kündigungsschutzklage verdict, i.e. exactly  */
/* the values a reader must be able to read. The brand colours themselves are        */
/* untouched — only the text on top changes, which lifts all three above 7:1.        */
.badge.bg-success,
.badge.bg-info,
.badge.bg-warning {
  color: var(--pd-ink-on-brand-fill);
}

/* The same correction for the circular icon tiles of the alert boxes, which the     */
/* badge rule above did not reach. Measured in the browser at 1440x900 with every    */
/* layer composited: the white glyph sits at 2.17:1 on --falcon-info and 2.61:1 on   */
/* --falcon-warning, in both themes — below the 3:1 that WCAG 2.2 SC 1.4.11 requires */
/* of a non-text element carrying meaning. These glyphs do carry it: they are the    */
/* success/warning/danger signal of the grade alert on the paid report pages, and    */
/* the same tile shows the hourglass of the report expiry banner. .bg-primary and    */
/* .bg-danger are deliberately not listed — they already measure 4.60:1 and 4.56:1   */
/* through the filled-variant correction CLAUDE.md records, and their glyphs stay    */
/* white. The 19 templates concerned had their .text-white class removed rather than */
/* this rule carrying !important: Bootstrap's utility is itself !important, so        */
/* overriding it would mean adding one more !important, which this file keeps for   */
/* the cases that have no other way. Nothing new is introduced — --pd-ink-on-brand-fill exists for */
/* exactly "the light brand fills (info, warning, success)".                         */
.bg-success.icon-item > .fas,
.bg-info.icon-item > .fas,
.bg-warning.icon-item > .fas,
.bg-success.icon-item > .fab,
.bg-info.icon-item > .fab,
.bg-warning.icon-item > .fab {
  color: var(--pd-ink-on-brand-fill);
}

/* The dark fills take white. The theme's gray-700 glyph measured 1.12:1 on the corrected
   primary and danger fills and 1.32:1 on secondary, where a product tile had no
   text-white (design run of 10.10.2026); white measures 4.60, 4.56 and 3.95:1. */
.bg-primary.icon-item > .fas,
.bg-danger.icon-item > .fas,
.bg-secondary.icon-item > .fas {
  color: #fff;
}

/* Minimal darkening of three Falcon text-emphasis tokens so the alert copy clears
   WCAG 2.2 SC 1.4.3 (AA) on its own tint. Measured in light mode, where these tints
   are used: #00894f on #d9f8eb was 3.96:1, #197aa4 on #d8f3ff 4.17:1, #ac5a2b on
   #fde6d8 4.11:1. Hue and saturation are unchanged; only lightness drops by 7.7 %,
   4.6 % and 5.6 % respectively, which is the smallest step that reaches 4.5:1. The
   danger pair (#b82c46 on #fcdfe4) already measures 4.82:1 and is left alone.
   Scoped to light mode because Falcon gives these tokens different, already-passing
   values on the dark surface. The alerts carry the grade verdict of the paid reports,
   so this is exactly the text a reader must be able to read. */
:root:not([data-bs-theme="dark"]) {
  --falcon-success-text-emphasis: #007e49;
  --falcon-info-text-emphasis: #18749c;
  --falcon-warning-text-emphasis: #a25529;

  /* Falcon's code colour is a light pink that only works on the dark surface: it
     measures 6.57:1 there but 2.74:1 on white. <code> is not decoration in this project
     — it carries the reference id on pages/failure.html and in the payment
     reconciliation notice, the one string a customer whose payment is stuck has to read
     off the screen and quote to support. #d63384 is Bootstrap's own code colour and
     measures 4.50:1 on white; the dark theme keeps the original, which already passes. */
  --falcon-code-color: #d63384;
}

/* White on the neutral secondary fill measures 3.95:1 — below AA at the size these
   buttons use (the purchase, download and example buttons of the three portfolio
   products in the colour "secondary", and the home button of the API failure page).
   Dark ink on the unchanged fill reaches 4.55:1.
   Darkening the fill instead would reach the same figure, but it would introduce a
   colour the project does not otherwise contain, and the inventory gate exists to stop
   exactly that. This way nothing is added: the fill stays --falcon-secondary and the ink
   is the same token the badges and the two brand-filled buttons already use. Hover and
   active keep the theme's white: on their darker fills (#636e7e, #5d6776) the dark ink
   measured 3.48 and 3.14:1, white 5.17 and 5.73:1. */
.btn-secondary {
  --falcon-btn-color: var(--pd-ink-on-brand-fill);
  --falcon-btn-disabled-color: var(--pd-ink-on-brand-fill);
}

/* Three brand fills were also being used as ink. Measured as rendered text on the light
   surfaces they actually sit on:
     .text-info    #27bcfd  1.88 - 2.17:1   (the "<60 Sek." figure on the homepage, the
                                             Arbeitszeugniserstellung headings, and the
                                             heading of the paywall overlay on its report)
     .text-success #00d27a  2.00:1
     .text-warning #f5803e  2.50 - 2.61:1   (including the severance amount on the
                                             Kündigungsanalyse report, set at 47.8 px —
                                             the single number that product exists to show)
   None of these reaches even the 3:1 that WCAG 2.2 SC 1.4.3 (AA) grants large text.
   Falcon already ships the ink variant of each hue as `--falcon-<name>-text-emphasis`,
   which the alert copy uses; pointing the text utilities at it lifts them to 4.58-5.43:1
   on every light surface while keeping the hue and therefore the product colour coding.
   The fills stay untouched, so a badge, a button and a heading of the same product still
   read as the same colour. The tokens invert with the theme, so the dark surface keeps
   its light ink automatically. Verified that none of the three classes sits on a dark
   fill anywhere: the only hits were icons on an 8 % tint, which composites to near-white.
   .text-primary and .text-danger are deliberately NOT remapped in THIS rule — at
   3.30-4.15:1 they were a borderline miss on the two most identity-defining hues, and
   that was the owner's call.
   RESOLVED, do not read this as still open: the owner decided on 20.08.2026, and both
   are remapped further down this same file — `.text-primary` for the light theme at the
   `:root:not([data-bs-theme="dark"]) .text-primary` rule and for the dark theme at its
   counterpart, `.text-danger`
   at its own rule beside `.btn-outline-primary`. Only the passage above is historical. */
.text-info {
  color: var(--falcon-info-text-emphasis) !important;
}

.text-success {
  color: var(--falcon-success-text-emphasis) !important;
}

.text-warning {
  color: var(--falcon-warning-text-emphasis) !important;
}

/* The same for the neutral hue, the product colour of three portfolio products since
   09.10.2026: #748194 measured 3.95:1 on white and 3.79:1 on the tertiary surface for
   their page headings and purchase prices (design run of 10.10.2026). The ink token is
   #5d6776 in light and #c7cdd4 in dark mode. */
.text-secondary {
  color: var(--falcon-secondary-text-emphasis) !important;
}

/* The same correction for the filled buttons on the info and warning colours. The dark
   ink of the badge rule further up reached badges only, so on every page the identical
   fill carried dark text as a badge and white text as a button — and the button failed WCAG 2.2 SC 1.4.3
   (AA) in each of its four states. Measured against the Falcon state variables:

     .btn-info      rest #27bcfd  hover #21a0d7  active #1f96ca
                    white  2.17     2.97           3.35    -> all below 4.5:1
                    dark   8.32     6.07           5.38    -> all above
     .btn-warning   rest #f5803e  hover #d06d35  active #c46632
                    white  2.61     3.55           3.97    -> all below
                    dark   6.89     5.08           4.54    -> all above

   These are not decorative buttons: .btn-info is the "Erstellungen" control in the top
   navigation of every page and every Arbeitszeugniserstellung CTA, .btn-warning carries
   the Kündigungsanalyse. The brand fills themselves stay untouched — only the ink on top
   changes, exactly as for the badges.
   .btn-primary is deliberately NOT in this list: white measures 4.14 / 5.40 / 6.00 and
   dark 4.35 / 3.33 / 3.00, so neither ink clears 4.5:1 in every state. That one can only
   be resolved by adjusting the brand colour itself and is the owner's decision.
   .btn-danger is the same case and is left out for the same reason:
     .btn-danger    rest #e63757  hover #c42f4a  active #b82c46
                    white  4.16     5.45           6.02
                    dark   4.33     3.30           2.99
   White fails only at rest and dark fails everywhere else, so swapping the ink would
   trade one failing state for two. It carries the "Erkannte Stellen und Formulierungs-
   alternativen freischalten" CTA under the grade-4 findings on both analysis reports —
   the second-most important purchase control of the two paid analysis products — so
   this is not a decorative shortfall. Like .btn-primary it needs the brand red itself
   to change, which is an identity decision and therefore the owner's.
   RESOLVED, do not read this as still open: the owner made that decision on 20.08.2026.
   The two filled surfaces are corrected further down this file, in the rule headed
   "Filled brand surfaces that carry white text" - `.btn-primary` to
   #1d72e3 (4.60:1) and `.btn-danger` to #e32346 (4.56:1), same hue, lightness down 3.2
   and 4.5 points. `--falcon-primary` and `--falcon-danger` keep the brand value; only the
   filled surfaces that carry white text moved. The analysis above is the record of how
   that decision came about, not of an open question.
   .btn-success joined this rule on 10.10.2026 (design run): no template used it until
   the portfolio products, whose colour is "success" for three of them, put it on their
   purchase and download buttons. White on #00d27a measured 2.0:1; the dark ink measures
   9.00 / 6.6 / 5.8 at rest, hover (#00b368) and active (#00a862). */
.btn-info,
.btn-success,
.btn-warning {
  --falcon-btn-color: var(--pd-ink-on-brand-fill);
  --falcon-btn-hover-color: var(--pd-ink-on-brand-fill);
  --falcon-btn-active-color: var(--pd-ink-on-brand-fill);
  --falcon-btn-disabled-color: var(--pd-ink-on-brand-fill);
}

/* Form placeholders carry the examples and formats of the product forms ("z. B. …"). The
   theme draws them in gray-400, 1.82:1 on white; gray-700 is the value .form-text took for
   the same reason (5.0:1). */
:root {
  --falcon-input-placeholder-color-global: var(--falcon-gray-700);
}

/* Text buttons (.btn-link) take their colour from --falcon-link-color, the hex variable
   that the link correction below leaves at #2c7be5: 3.95:1 on a tinted block, measured
   on the report's copy control while it was a text button. That control is a
   btn-falcon-default since 10.10.2026 and no public template uses .btn-link today; the
   rule stays so that the next one follows the body links, which read
   --falcon-link-color-rgb in both themes. */
.btn-link {
  --falcon-btn-color: rgb(var(--falcon-link-color-rgb));
  --falcon-btn-hover-color: rgb(var(--falcon-link-color-rgb));
  --falcon-btn-active-color: rgb(var(--falcon-link-color-rgb));
}

/* The same failure in the soft button variants, which the rule above does not reach:
   they draw their ink from a different variable and sit on --falcon-quaternary-bg
   (#ffffff in light mode) rather than on the brand fill. Measured there:
   #f5803e on #ffffff = 2.61:1 (2.50:1 on the tertiary surface #f9fafd) and
   #27bcfd on #ffffff = 2.17:1, against the 4.5:1 that SC 1.4.3 (AA) requires.
   These are not decorative either: .btn-falcon-warning is the "Übersicht" control at
   the head of all 30 Kündigung articles, .btn-falcon-info the Arbeitszeugniserstellung
   CTA in includes/jobreference.html. Dark mode already passes (6.89:1 / 8.32:1), which
   is why the gap survives development unnoticed.

   The ink is NOT set to --pd-ink-on-brand-fill here, which the filled buttons use: on a
   white ground that near-black would pass at ~16:1 but would erase the product colour
   the soft button exists to carry — every variant would look alike. It reuses the two
   text-emphasis tokens this file already darkened for the alert copy instead, so no new
   colour enters the palette and the button stays recognisably warning/info:
   #a25529 on #ffffff = 5.43:1 (5.20:1 on #f9fafd), #18749c = 5.23:1 (5.01:1). */
.btn-falcon-warning {
  --falcon-btn-falcon-warning-color: var(--falcon-warning-text-emphasis);
  --falcon-btn-falcon-warning-hover-color: var(--falcon-warning-text-emphasis);
  --falcon-btn-falcon-warning-active-color: var(--falcon-warning-text-emphasis);
}

.btn-falcon-info {
  --falcon-btn-falcon-info-color: var(--falcon-info-text-emphasis);
  --falcon-btn-falcon-info-hover-color: var(--falcon-info-text-emphasis);
  --falcon-btn-falcon-info-active-color: var(--falcon-info-text-emphasis);
}

/*
  Text-level contrast of the brand colour, light theme only.

  `--falcon-primary` (#2c7be5) reaches only 4.14:1 on white, while WCAG 2.2 AA requires
  4.5:1 for normal text. Measured across 942 nodes: every in-body link of the blog
  articles, every FAQ heading and the brand name in the footer. This rule fixes the
  `.text-primary` share of that. Body links draw their colour from the compiled theme
  through a different route: Falcon's `a` rule reads `--falcon-link-color-rgb`, which the
  rule below this one sets for the light theme and its dark counterpart sets for the dark
  one. Both are closed. (An earlier version of this comment pointed at a file
  `befunde/K21.md`, which does not exist in this repository - that was the working
  directory of a finished run and is gone.)

  #2569c3 is not a new colour — it is Falcon's own primary hover tone and already lives
  in this file as `--badge-primary-hover`. It raises body links and `.text-primary` to
  5.40:1 and is indistinguishable from the brand colour at 13px, so filled surfaces
  (buttons, badges, banners) keep the exact brand value and stay untouched.

  The `[data-bs-theme="light"]` scope is load-bearing, not decoration. On the dark
  background the same substitution moves the ratio the wrong way — measured 4.06:1 → 3.11:1
  for body links and 3.32:1 → 2.54:1 for `.text-primary`. Dark needs a *lighter* tone,
  which no existing project value supplies (`--falcon-info` is semantically bound to the
  Arbeitszeugniserstellung), so that half stays open rather than being made worse here.
  RESOLVED, do not read this as still open: the dark half is closed by the
  `[data-bs-theme="dark"] .text-primary` rule and the dark body-link tone below.

  `!important` on `.text-primary` is required because the Bootstrap utility it overrides
  carries `!important` itself.
*/
/* Written as `:root:not([data-bs-theme="dark"])` for the reason given at the two
   light token blocks below: with JavaScript disabled the IIFE in `base.html` never
   writes the attribute, and this rule then did not apply — measured in Chromium with
   no attribute set, `.text-primary` rendered rgb(44, 123, 229), the uncorrected brand
   value at 4.14:1, while the body links beside it were already corrected. The scope
   still has to exclude the dark theme, where the same substitution moves the ratio
   the wrong way (3.32:1 → 2.54:1), and `:not([data-bs-theme="dark"])` does that. */
:root:not([data-bs-theme="dark"]) .text-primary {
  color: var(--badge-primary-hover) !important;
}

/*
  Body links, light theme only, same tone and same reason as above.

  Falcon's `a` rule reads `--falcon-link-color-rgb`, not `--falcon-link-color`, so setting
  the hex variable has no effect at all — measured: the link stayed at #2c7be5 / 4.14:1.
  37, 105, 195 is #2569c3 in the channel form that rule expects, which lifts every in-body
  link of the 143 articles to 5.40:1.

  Hover is deliberately left alone: it is a transient state, not the one a reader spends
  their time on, and Falcon derives it from its own variable.
*/
/* `:root:not([data-bs-theme="dark"])` rather than `[data-bs-theme="light"]`, and the
   difference is not stylistic: the attribute is written by the IIFE in `base.html`, so
   with JavaScript disabled there is no attribute at all. The light corrections a few
   hundred lines above already use this form and therefore applied in that state, while
   this one did not — the page then rendered with half of the light token set, links at
   4.14:1 among values that were corrected. */
:root:not([data-bs-theme="dark"]) {
  --falcon-link-color-rgb: 37, 105, 195;
}

/*
  Soft buttons: text colour of the primary and danger variants.

  `.btn-falcon-primary` paints its label in `--falcon-primary` (#2c7be5), which reaches
  4.14:1 on white where WCAG 2.2 AA (1.4.3) asks for 4.5:1 at 16px/500 — measured on
  nine nodes across the blog overview, the JRA/JCA formulars and both analysis reports.
  `.btn-falcon-danger` has the same defect at 4.16:1 with `--falcon-danger` (#e63757),
  on the "Bericht deaktivieren" control of every report page.

  The substitution is the project's own pattern, not a new decision: the
  `.btn-falcon-info` rule a few lines above already swaps in Falcon's own
  `*-text-emphasis` tone for exactly this reason. That variable is theme-aware, so one
  rule fixes both themes — light #215cac (6.58:1) / #b82c46 (6.02:1), dark #abcaf5
  (10.72:1) / #f4a5b3 (9.33:1). No new colour value enters the project and the filled
  brand surfaces stay untouched.
*/
.btn-falcon-primary {
  --falcon-btn-falcon-primary-color: var(--falcon-primary-text-emphasis);
  --falcon-btn-falcon-primary-hover-color: var(--falcon-primary-text-emphasis);
  --falcon-btn-falcon-primary-active-color: var(--falcon-primary-text-emphasis);
}

.btn-falcon-danger {
  --falcon-btn-falcon-danger-color: var(--falcon-danger-text-emphasis);
  --falcon-btn-falcon-danger-hover-color: var(--falcon-danger-text-emphasis);
  --falcon-btn-falcon-danger-active-color: var(--falcon-danger-text-emphasis);
}

/*
  Brand text on the light-theme brand tint.

  `.text-primary` sits at #2569c3 since the light-theme correction above, which clears
  4.5:1 on white but only reaches 4.31:1 on `--falcon-primary-bg-subtle` (#d9e7fa) —
  the rating badge and the reviewer initials of the JTA formular, ten nodes. The tint is
  a derived value, not a brand colour, so it is the part that moves: 20 % towards white
  lifts the pair to 4.53:1 and stays visually a pale brand blue.
*/
/* Same reasoning as the link-colour rule above: written so it also holds when no
   theme attribute is present. The two light blocks stay apart rather than being
   merged, because each carries the measurement that justifies it and moving the
   declarations away from their comment is what makes such a value look arbitrary
   later. */
:root:not([data-bs-theme="dark"]) {
  --falcon-primary-bg-subtle: #e1ecfb;
}

/*
  Secondary badges.

  White on `--falcon-secondary` (#748194) reaches 3.95:1. The badge carries "Nach
  Freischaltung" and the masked "?" of an unpaid report — the two places where a
  prospective buyer reads what is being withheld, so it is exactly the label that has to
  be legible. #697787 lifts it to 4.58:1. `--falcon-secondary` is a Falcon neutral and
  does not appear in the brand table, and the override is scoped to the badge so no
  other surface moves with it.
*/
.badge.bg-secondary {
  background-color: #697787 !important;
}

/*
  Range slider focus, JRC rating controls.

  Bootstrap draws the focused thumb with a translucent halo (rgba(44,123,229,.25),
  about 1.3:1 against white), which is the weakest focus indicator in the project while
  the three sliders it belongs to decide the grades of the certificate the visitor pays
  for. The ring below reuses the same 2px `--falcon-primary` the project already puts on
  every other control; the inner ring in the body colour keeps it readable on the track.
  `outline` cannot be used here — it applies to the input box, not to the thumb.
*/
.form-range:focus-visible::-webkit-slider-thumb {
  box-shadow:
    0 0 0 2px var(--falcon-body-bg),
    0 0 0 4px var(--falcon-primary);
}

.form-range:focus-visible::-moz-range-thumb {
  box-shadow:
    0 0 0 2px var(--falcon-body-bg),
    0 0 0 4px var(--falcon-primary);
}

/*
  Brand text in the dark theme.

  This is the half the light-theme correction above deliberately left open: on dark
  backgrounds `--falcon-primary` reaches 4.06:1 on #121e2d, 3.88:1 on #162231 and
  3.12:1 inside the improvement block — 155 nodes, the largest single contrast defect in
  the project. It needs a *lighter* tone, and Falcon ships one: the theme's own
  `--falcon-primary-text-emphasis` resolves to #abcaf5 in dark mode and reaches
  9.56:1 to 10.72:1 on those same backgrounds. Same hue, no new colour value, and the
  filled brand surfaces are untouched — a dark-theme heading and a body link simply stop
  being painted in the tone meant for light backgrounds.

  Both rules are scoped to `[data-bs-theme="dark"]`, mirroring the light-theme block,
  because the same substitution moves the light theme the wrong way.
*/
[data-bs-theme="dark"] .text-primary {
  color: var(--falcon-primary-text-emphasis) !important;
}

/*
  The theme switch itself, dark theme. Falcon paints both of its labels with the raw
  --falcon-primary, which measures 2.54:1 against the dark surface rgb(52,64,80) —
  below the 3:1 that WCAG 2.2 SC 1.4.11 requires of a control, and this one sits in
  the header of every single page. The same substitution the rule above makes for
  .text-primary lifts it to 6.26:1, measured in the browser. #abcaf5 is not a new
  value: it is the dark theme's own link colour, set in the "Body links, dark theme"
  rule below. The light
  theme is untouched and already passes at 3.16:1.
*/
[data-bs-theme="dark"] .theme-control-toggle-label {
  color: var(--falcon-primary-text-emphasis);
}

/*
  Body links, dark theme. Falcon reads `--falcon-link-color-rgb`, not the hex variable,
  so the tone has to be written in channel form: 171, 202, 245 is #abcaf5.
*/
[data-bs-theme="dark"] {
  --falcon-link-color-rgb: 171, 202, 245;
  /* The hover tone needs the same correction: the theme's #2362b7 measured 2.36 to
     3.00:1 on the dark surfaces. #d9e7fa is the next lighter step of the same primary
     scale (the light theme's primary-bg-subtle). */
  --falcon-link-hover-color-rgb: 217, 231, 250;
}

/*
  Outline buttons and danger text — the two remaining text usages of a semantic colour.

  `.btn-outline-primary` paints its resting label in `--falcon-primary` (4.14:1 light,
  4.06:1 dark) and `.text-danger` paints it in `--falcon-danger` (3.99:1 on the tertiary
  card background). The second one carries the two sentences of the Kündigungsanalyse
  that state whether the § 4 KSchG deadline has run out — the most consequential text in
  the free product.

  Both take the same route as the soft buttons above: Falcon's own theme-aware
  `*-text-emphasis` tone, so no new colour value enters the project and both themes are
  covered by one rule. Filled surfaces, borders and hover states keep the exact brand
  value; only the resting label moves. Measured light 6.58:1 / 5.77:1, dark 10.72:1 /
  9.33:1.
*/
.btn-outline-primary {
  --falcon-btn-color: var(--falcon-primary-text-emphasis);
}

.text-danger {
  color: var(--falcon-danger-text-emphasis) !important;
}

/*
  Filled brand surfaces that carry white text — the owner's decision of 20.08.2026.

  White on `--falcon-primary` (#2c7be5) measures 4.14:1 and on `--falcon-danger`
  (#e63757) 4.16:1, against the 4.5:1 WCAG 2.2 AA (1.4.3) asks for at these sizes.
  Sixty places, among them every `.badge.bg-primary` of the article lists, the two
  header buttons, the "Auffällige Stelle N" badges of both analysis reports and the
  purchase button itself.

  The correction is the smallest one that clears the threshold: the hue is untouched
  (214.4° and 349.0°) and only the lightness drops, by 3.2 and 4.5 points respectively.
  Measured 4.14 → 4.60:1 and 4.16 → 4.56:1. Side by side the two blues are practically
  indistinguishable, which is the point — the owner picked this over the larger step to
  the already-approved #2569c3 (5.40:1).

  `--falcon-primary` and `--falcon-danger` themselves stay at the exact brand value:
  borders, focus rings, the soft button family and the tinted backgrounds all continue
  to read them. Only the surfaces that paint white text on top move, and they move
  through the same rgb variable Bootstrap's opacity utilities use, so
  `.bg-primary.bg-opacity-25` keeps working.
*/
.btn-primary {
  --falcon-btn-bg: var(--pd-primary-fill);
  --falcon-btn-border-color: var(--pd-primary-fill);
}

.btn-danger {
  --falcon-btn-bg: var(--pd-danger-fill);
  --falcon-btn-border-color: var(--pd-danger-fill);
}

.bg-primary {
  --falcon-primary-rgb: var(--pd-primary-fill-rgb);
}

.bg-danger {
  --falcon-danger-rgb: var(--pd-danger-fill-rgb);
}

/* Report blocks of the portfolio products (products/blocks.py, 10.10.2026).
   Bars are native <progress> elements so their width is the element's value and no
   inline style is needed; each engine draws them, so both pseudo-elements are styled. */
.pd-bar {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 0.75rem;
  border: 0;
  border-radius: var(--falcon-border-radius-lg);
  background-color: var(--falcon-gray-200);
  overflow: hidden;
}

.pd-bar::-webkit-progress-bar {
  background-color: var(--falcon-gray-200);
  border-radius: var(--falcon-border-radius-lg);
}

.pd-bar::-webkit-progress-value {
  background-color: var(--pd-bar-color, var(--falcon-primary));
  border-radius: var(--falcon-border-radius-lg);
}

.pd-bar::-moz-progress-bar {
  background-color: var(--pd-bar-color, var(--falcon-primary));
  border-radius: var(--falcon-border-radius-lg);
}

.pd-bar--success {
  --pd-bar-color: var(--falcon-success);
}

.pd-bar--warning {
  --pd-bar-color: var(--falcon-warning);
}

.pd-bar--danger {
  --pd-bar-color: var(--falcon-danger);
}

.pd-bar--muted {
  --pd-bar-color: var(--falcon-gray-500);
}

/* The deadline calendar: a vertical line with one dot per date. A deadline gets a
   ring, a past date a muted dot, the next days a warning colour. */
.pd-timeline {
  position: relative;
  padding-left: 1.5rem;
}

.pd-timeline__item {
  position: relative;
  padding-bottom: 1rem;
}

/* The line is 2 px wide and centred on the 1rem dots, whose centre lies 0.5rem in and
   0.75rem down. Each item draws the segment from its own dot to the next one: drawn on
   the list, the line ran 17 px past the last dot at 1440 px and 152 px at 320 px, where
   the last date wraps under a note (design run of 10.10.2026). */
.pd-timeline__item:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 0.75rem;
  bottom: -0.75rem;
  left: calc(-1rem - 1px);
  /* A border rather than a background, as .pd-steps draws its line: it prints without
     background graphics and stays visible under forced colours. */
  border-left: 2px solid var(--falcon-gray-300);
}

.pd-timeline__item:last-child {
  padding-bottom: 0;
}

.pd-timeline__dot {
  position: absolute;
  top: 0.25rem;
  left: -1.5rem;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background-color: var(--falcon-primary);
  border: 2px solid var(--falcon-card-bg, #fff);
}

.pd-timeline__item--past .pd-timeline__dot {
  background-color: var(--falcon-gray-500);
}

.pd-timeline__item--soon .pd-timeline__dot,
.pd-timeline__item--today .pd-timeline__dot {
  background-color: var(--falcon-warning);
}

.pd-timeline__item--deadline .pd-timeline__dot {
  box-shadow: 0 0 0 3px rgba(var(--falcon-danger-rgb), 0.35);
}

/* A scale between two poles with a marker, for the self-employment tendency. */
.pd-scale {
  position: relative;
  height: 0.75rem;
  border-radius: var(--falcon-border-radius-lg);
  background: linear-gradient(
    90deg,
    var(--falcon-success),
    var(--falcon-warning),
    var(--falcon-danger)
  );
}

.pd-scale__marker {
  position: absolute;
  top: -0.35rem;
  width: 0.25rem;
  height: 1.45rem;
  margin-left: -0.125rem;
  border-radius: var(--falcon-border-radius);
  background-color: var(--falcon-gray-1100);
}

/* Eleven marker positions in steps of ten percent; a class rather than an inline
   left offset, so the template carries no style attribute. */
.pd-scale__marker--0 {
  left: 0%;
}
.pd-scale__marker--10 {
  left: 10%;
}
.pd-scale__marker--20 {
  left: 20%;
}
.pd-scale__marker--30 {
  left: 30%;
}
.pd-scale__marker--40 {
  left: 40%;
}
.pd-scale__marker--50 {
  left: 50%;
}
.pd-scale__marker--60 {
  left: 60%;
}
.pd-scale__marker--70 {
  left: 70%;
}
.pd-scale__marker--80 {
  left: 80%;
}
.pd-scale__marker--90 {
  left: 90%;
}
.pd-scale__marker--100 {
  left: 100%;
}

/* Tiles of a requirement check, three to a row on wide screens. They carry the finding
   pattern below (.pd-finding with its rating modifier), so a rated point looks the same
   in every report; only the height and the closer padding of a tile differ. */
.pd-finding.pd-check-tile {
  height: 100%;
  margin-bottom: 0;
  padding: 0.5rem 1rem;
}

/* Product forms: a numbered heading above each group of questions. The number sits in a
   circle in the primary colour; the hint underneath is indented to the heading text. */
.pd-form-section {
  margin-top: 0.5rem;
}

.pd-form-section__number {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: rgba(var(--falcon-primary-rgb), 0.12);
  /* The emphasis ink of the primary colour, as .btn-falcon-primary uses: the plain
     primary measured 3.6:1 on this tint (design run of 10.10.2026). */
  color: var(--falcon-primary-text-emphasis);
  font-weight: 600;
  font-size: 0.8333333333rem;
}

/* Points of a product page's method card: icon beside a short title and text. */
.pd-method-item {
  display: flex;
  gap: 1rem;
  padding: 1rem;
  border: 1px solid var(--falcon-border-color);
  border-radius: var(--falcon-border-radius-lg);
}

.pd-method-item__icon {
  margin-top: 0.25rem;
}

/* The checked points of an unpaid analysis: a plain numbered list with room per line. */
.pd-checked-list {
  padding-left: 1.25rem;
}

.pd-checked-list > li {
  padding: 0.25rem 0;
}

/* An icon that belongs to the word before it: Font Awesome sets .fas inline-block, and
   a line may break before an inline-block even after a no-break space. */
.pd-inline-icon {
  display: inline;
}

/* Next steps of a paid analysis: numbered circles on a thin connecting line. */
.pd-steps {
  list-style: none;
  counter-reset: pd-step;
  padding-left: 0;
}

.pd-steps__item {
  position: relative;
  counter-increment: pd-step;
  padding: 0 0 1rem 3rem;
}

.pd-steps__item::before {
  content: counter(pd-step);
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  /* The filled primary that carries white text since the owner's decision of 20.08.2026
     (the rule "Filled brand surfaces that carry white text" further up): white on the
     plain #2c7be5 is 4.14:1. */
  background: var(--pd-primary-fill);
  color: #fff;
  font-weight: 600;
  font-size: 0.8333333333rem;
}

.pd-steps__item:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 2.25rem;
  bottom: 0.25rem;
  left: calc(1rem - 1px);
  border-left: 2px solid var(--falcon-border-color);
}

.pd-steps__item:last-child {
  padding-bottom: 0;
}

/* One finding of a paid analysis: a card-like block whose left edge carries the rating
   colour, as the Arbeitszeugnisanalyse marks a graded sentence. The colour comes from a
   modifier of its own; the border-* utility it used to take is !important in Bootstrap
   and needed six !important declarations to be overridden again. */
.pd-finding {
  padding: 1rem;
  margin-bottom: 1rem;
  border: 1px solid var(--falcon-border-color);
  border-left-width: 4px;
  border-left-color: var(--falcon-gray-400);
  border-radius: var(--falcon-border-radius-lg);
}

.pd-finding--danger {
  border-left-color: var(--falcon-danger);
}

.pd-finding--warning {
  border-left-color: var(--falcon-warning);
}

.pd-finding--success {
  border-left-color: var(--falcon-success);
}

/* The three parts of a finding: small uppercase labels above each paragraph. */
.pd-finding__parts dt {
  margin-top: 0.5rem;
  color: var(--falcon-gray-700);
  font-size: 0.6944444444rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* A statute cited beside a label ("§ 1a KSchG") keeps its spelling: the label's capitals
   turned it into "§ 1A KSCHG", and the badge's 0.75em made it 9 px. */
.pd-finding__parts dt .badge {
  font-size: 0.6944444444rem;
  letter-spacing: 0;
  text-align: left;
  text-transform: none;
  /* A long citation ("§ 1 Abs. 3 Satz 1 Halbsatz 2 KSchG") overran 320 px by 17 px. */
  white-space: normal;
}

.pd-finding__parts dd {
  margin-bottom: 0;
  color: var(--falcon-gray-900);
}

/* A quotation from the uploaded document. */
.pd-quote {
  margin: 0 0 0.5rem;
  padding: 0.5rem 1rem;
  border-left: 3px solid var(--falcon-gray-400);
  background: var(--falcon-tertiary-bg);
  border-radius: 0 var(--falcon-border-radius-lg) var(--falcon-border-radius-lg) 0;
  color: var(--falcon-gray-1100);
}

/* A wording the buyer can copy: a quiet box with a dashed primary border. */
.pd-wording {
  margin-top: 1rem;
  padding: 0.5rem 1rem;
  border: 1px dashed rgba(var(--falcon-primary-rgb), 0.5);
  border-radius: var(--falcon-border-radius-lg);
  background: rgba(var(--falcon-primary-rgb), 0.04);
}

/* A wording that the model wrote as lines (a CV's list of tasks) keeps them, on the page
   and in what the copy button reads from it. */
.pd-wording > p {
  white-space: pre-line;
}

/* The created document drawn as a sheet of paper: white in both modes, because the
   buyer reads it as the letter or contract they will print. It takes the full width of
   its card (global rule: readable text is never narrowed to a reading measure). */
.pd-paper {
  position: relative;
  padding: 3rem;
  background: var(--pd-paper-bg);
  border: 1px solid var(--falcon-border-color);
  border-radius: var(--falcon-border-radius);
  box-shadow: var(--falcon-box-shadow-sm);
}

.pd-paper__text,
.pd-paper__text p,
.pd-paper__text li {
  color: var(--pd-paper-ink);
  line-height: 1.5;
}

.pd-paper__text p {
  margin-bottom: 1rem;
}

/* Paragraph or list, the last block leaves the bottom padding alone, as the first does
   at the top. */
.pd-paper__text > :last-child {
  margin-bottom: 0;
}

.pd-paper__text .pd-paper__heading {
  margin-top: 1.5rem;
  margin-bottom: 0.5rem;
  font-weight: 700;
}

/* The sheet's own padding is the top margin of its first block; a heading there would
   add its 1.5rem on top (measured 72 px of empty paper above the salary guide). */
.pd-paper__text > :first-child {
  margin-top: 0;
}

/* The list marks are text, not ::marker: copying and printing read the sheet's innerText,
   which carries no ::marker, and the numbers and dashes of the document went missing
   from both (design run of 10.10.2026). The marker box hangs in the indent. */
.pd-paper__list {
  margin-bottom: 1rem;
  padding-left: 1.5rem;
  list-style: none;
}

.pd-paper__list > li {
  text-indent: -1.5rem;
}

/* A list joined from items the text set apart keeps that space between them. */
.pd-paper__list--spaced > li + li {
  margin-top: 1rem;
}

.pd-paper__marker {
  display: inline-block;
  width: 1.25rem;
  text-indent: 0;
}

/* The unpaid preview fades out where the free part ends. The fade is decoration only:
   the server sends the free part and nothing more (CLAUDE.md > Invariants for Audit Runs). */
.pd-paper--preview {
  overflow: hidden;
}

.pd-paper--preview::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 5rem;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--pd-paper-bg));
  border-radius: 0 0 var(--falcon-border-radius) var(--falcon-border-radius);
}

/* Placeholders the buyer still fills in, marked in the sheet with the light values of
   the warning role (Falcon has no yellow); the sheet stays white in both modes, so the
   values are fixed rather than theme variables. The mark has no side padding: its own
   brackets are its edges, and a 4 px inset read as a space before the next comma
   ("[Ort] , [Datum]", design run of 10.10.2026). */
.pd-placeholder {
  padding: 0;
  border-radius: var(--falcon-border-radius);
  background: var(--pd-placeholder-bg);
  color: var(--pd-paper-ink);
}

@media (max-width: 575.98px) {
  .pd-paper {
    padding: 1.5rem 1rem;
  }
}

/* Below the sm breakpoint a three-column table of the report stacks each row into one
   block (label, value, rating) instead of hiding its last column behind a horizontal
   scroll; the rows keep one rule each, and the cells share one left edge. */
@media (max-width: 575.98px) {
  /* The column heads stay for screen readers: hidden with d-none, the stacked cells
     lost their column names (WCAG 2.2 SC 1.3.1). Visually hidden as .visually-hidden. */
  .pd-stack-table thead {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
  }

  .pd-stack-table tbody tr {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--falcon-border-color);
  }

  /* The theme indents the first and last cell of a row (.table tr th:first-child,
     1.25rem, specificity 0-2-2); in the stacked form every cell starts on the same edge. */
  .table.pd-stack-table tbody tr > :is(th, td) {
    padding: 0.25rem 0;
    border-bottom-width: 0;
  }

  /* Where two values of a row are amounts, the stacked cell names its column, or
     "366,63 €" and "358,25 €" could not be told apart (payslip comparison). */
  .pd-stack-table td[data-label]::before {
    content: attr(data-label) ": ";
    color: var(--falcon-gray-700);
  }
}

/* The questions under the purchase card and the toggle of the original document on the
   two analysis reports ("Ihr ursprüngliches Arbeitszeugnis anzeigen") only changed the
   pointer on hover; they take the link ink like the footer links. */
@media (hover: hover) {
  details > summary:hover {
    color: rgb(var(--falcon-link-color-rgb));
  }
}

/* The leading icon of a link list keeps its fixed width: as a flex item it shrank from
   24 to 14.4 px beside a wrapping title, and the titles of one list started at
   different points. */
.list-group-item-action > .fas:first-child {
  flex-shrink: 0;
}

/* Dates and amounts that stand under one another outside a table take the tabular
   figures the tables already have (the td, th rule further up). */
.pd-figures {
  font-variant-numeric: tabular-nums;
}

/* On paper the sheet is the page: no frame, no inset, no shadow. The placeholders keep
   only their brackets, which survive printing without background graphics. */
@media print {
  .pd-paper {
    padding: 0;
    border: 0;
    box-shadow: none;
  }

  .pd-placeholder {
    background: none;
  }
}

/* Final pass of the design run, 12.10.2026. */

/* The theme selects text in --falcon-primary (white at 4.14:1) and, in dark mode, in the
   orange of the dismissal products (white at 2.61:1). Selection takes the brand fill in
   both modes. */
::selection,
[data-bs-theme="dark"] ::selection {
  background-color: var(--pd-primary-fill);
  color: #fff;
}

/* The theme draws the arrow of a select in #4d5969 in both modes: 2.53:1 on the dark
   field, and the arrow is what tells a select from a text field (WCAG 2.2 SC 1.4.11).
   gray-600 (#748194) measures above 4:1 there. */
[data-bs-theme="dark"] .form-select {
  --falcon-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23748194' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* A badge is 0.75em of its parent, which put the verdict of a check at 10 px inside
   fs-10 text, below the smallest step of the scale (fs-11, 11.1 px). The floor lifts
   only those; a badge with a size class of its own keeps it. */
.content .badge {
  font-size: max(0.75em, 0.6944444444rem);
}

/* A field the visitor has left invalid, or that a refused submit found empty, shows it
   at the field and not only in the browser's passing bubble at the first one. */
.form-control:user-invalid,
.form-select:user-invalid,
.form-check-input:user-invalid {
  border-color: var(--falcon-danger);
}

/* The consent switches sat 24 px further in than every field above them: the column
   carries .form-switch, whose 2.5em indent is meant for the inner .form-check. Crispy
   renders the column as "col-md form-switch", so the selector matches any col class. */
.form-switch[class*="col"] {
  padding-left: calc(var(--falcon-gutter-x) * 0.5);
}

/* The 3 px accent of a card (border-3) reaches its buttons through the inherited
   --falcon-border-width and drew them with a 3 px frame. Their frame returns to 1 px;
   the padding takes the 2 px per side back, so the buttons keep their 40 px height
   (a target never shrinks in this run). */
.card.border-3 .btn:not(.btn-sm):not(.btn-lg) {
  --falcon-btn-border-width: 1px;
  --falcon-btn-padding-y: calc(0.3125rem + 2px);
}

/* Placeholder marks outside the white sheet (the list of placeholders, the summary,
   the notes and the wordings of a report) take the dark warning tint in dark mode; the
   sheet and its preview stay white and keep the light marks. */
[data-bs-theme="dark"] .pd-placeholder:not(.pd-paper .pd-placeholder) {
  --pd-placeholder-bg: var(--falcon-warning-bg-subtle);
  color: var(--falcon-warning-text-emphasis);
}

/* The printed report link wraps where it must: it is one long word. */
.pd-print-link {
  overflow-wrap: anywhere;
}

@media print {
  [data-report-link] {
    break-inside: avoid;
  }
}

/* The focus ring sits 2 px outside a control, and the navigation lists clip their
   overflow: on the sidebar links, the hamburger menu and the product menus only two
   horizontal lines of it were left. Inside those lists the ring is drawn inward. */
.navbar-vertical .nav-link:focus-visible,
.navbar .pd-nav-menu .dropdown-item:focus-visible {
  outline-offset: -2px;
}

/* The collapsed sidebar from 1200 px was fixed to the height of its container (h-100)
   while the theme clips the list, so with a mouse or by touch its lower links (Über uns,
   the guides, the legal pages) could not be reached; the content around it scrolls once
   the list takes its own height. */
@media (min-width: 1200px) {
  .navbar-vertical .navbar-collapse .navbar-vertical-content > #navbarVerticalNav {
    height: auto !important;
  }
}

/* The opened sidebar is 234 px wide, and the longer product names broke in the middle of
   a word without a hyphen ("Aufhebungsvertragsanaly-se"). */
.navbar-vertical .nav-link-text {
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* The consent library resets its buttons (all: initial; outline: revert), which left
   them without a visible ring in WebKit; they take the project's ring. The extra
   element wins against the library, which loads after this file. */
html #cc-main :focus-visible {
  outline: 2px solid var(--falcon-primary);
  outline-offset: 2px;
}

/* A required field left empty names its problem at the field, not only in the browser's
   passing bubble at the first one (custom.js, initializeRequiredFieldMessages). */
.pd-required-error {
  font-size: 0.8333333333rem;
}
