/* ============================================================================
 * LeadSuche — Master Stylesheet · Marketing Site + App Shell
 * Plus Jakarta Sans · Blue/Red Gradient · single --ds-* token namespace
 *
 * Structure: @font-face → ONE :root (all tokens) → base/reset → typography →
 * shared primitives (forms bridge, alerts, blog, badges) → marketing
 * components (one-pager, landing sections, hero) → Phase-2 ds components
 * (buttons, cards, forms, tables, shells, sidebar, footer) → app components
 * (search/filter, records, billing, detail) → late component singletons →
 * @media print (always last).
 *
 * Cascade rule of thumb: a component's LAST definition block is its home;
 * earlier blocks only carry layout-era groundwork. Never re-style a
 * component by appending an override layer at the end of the file — edit
 * its home block instead.
 * ============================================================================ */

/* === Plus Jakarta Sans (Variable Font, self-hosted, GDPR-compliant) === */
@font-face {
  font-family: "Plus Jakarta Sans";
  src:
    url("../fonts/PlusJakartaSans-VariableFont.52d04440a9fa.woff2")
      format("woff2-variations"),
    url("../fonts/PlusJakartaSans-VariableFont.52d04440a9fa.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* === Bootstrap Icons (self-hosted) === */
@font-face {
  font-family: "bootstrap-icons";
  src:
    url("../fonts/bootstrap-icons/bootstrap-icons.cc1e5eda776b.woff2") format("woff2"),
    url("../fonts/bootstrap-icons/bootstrap-icons.ba49e8448923.woff") format("woff");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* === JetBrains Mono (self-hosted, GDPR-compliant) === */
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono/JetBrainsMono-Regular.4e0581ae831b.woff2")
    format("woff2");
  /* Literal, not var(): custom properties are not allowed in @font-face
     descriptors, so a var() here is dropped and every face falls back to
     the initial weight 400 — all three files would claim the same weight. */
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono/JetBrainsMono-Medium.ef0a72739771.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono/JetBrainsMono-Bold.f3651b6798df.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* === Brand Variables === */
:root {
  /* Bootstrap variable overrides — re-point Bootstrap's own tokens to the
       brand --ds-* set so framework components inherit the design system. */
  --bs-primary: var(--ds-blue);
  --bs-primary-rgb: var(--ds-blue-rgb);
  --bs-link-color: var(--ds-blue);
  --bs-link-hover-color: var(--ds-blue-dark);
  --bs-body-font-family: var(--ds-font-display);
  --bs-body-color: var(--ds-ink);
  --bs-heading-color: var(--ds-ink);
  --bs-border-radius: var(--ds-radius-xs);
  --bs-border-radius-lg: var(--ds-radius-sm);
  --bs-border-radius-xl: var(--ds-radius-md);

  color-scheme: light;

  /* ========================================================================
     * .ds-* Design System Tokens — the sole token set, defined in this ONE
     * :root block. The legacy namespaces (--base-color era, --ds-op-* one-pager
     * era, standalone sidebar block) were all folded into this set.
     * ====================================================================== */

  /* Brand */
  --ds-blue: #074eb9;
  --ds-red: #e94037;
  --ds-purple: #724ade;

  /* Ink (Text) */
  --ds-ink: #252840;
  --ds-ink-soft: #5c6077;
  --ds-ink-mute: #60657f;

  /* Surfaces */
  --ds-surface: #ffffff;
  --ds-surface-tint: #f5f7fc;
  --ds-surface-muted: #edf1f9;
  --ds-surface-dark: #0a0f1a;
  --ds-surface-dark-2: #0f1a30;

  /* Status (WCAG AA-verified on --ds-surface + --ds-surface-tint) */
  --ds-success: #077a3d;
  --ds-warn: #b45309;
  --ds-danger: #c92d24;
  --ds-info: #1d4ed8;

  /* Status-Tints (low-opacity backgrounds for alerts, badges, icon-halos).
       Use as: background: var(--ds-success-tint); color: var(--ds-success); */
  --ds-success-tint: rgba(var(--ds-success-rgb), 0.1);
  --ds-warn-tint: rgba(var(--ds-warn-rgb), 0.1);
  --ds-danger-tint: rgba(var(--ds-danger-rgb), 0.1);
  --ds-info-tint: rgba(var(--ds-info-rgb), 0.1);
  /* Brighter "live/positive" green used for activity dots, sparkline deltas
       and score chips. Distinct from the status-green --ds-success (#077a3d),
       which is reserved for form/alert success states. Both are intentional;
       this token only centralizes the value that was previously inlined. */
  --ds-success-bright: #22c55e;

  /* Signature Gradients */
  --ds-gradient-brand: linear-gradient(
    135deg,
    var(--ds-blue) 0%,
    var(--ds-purple) 50%,
    var(--ds-red) 100%
  );
  --ds-gradient-brand-soft: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.12) 0%,
    rgba(var(--ds-purple-rgb), 0.1) 50%,
    rgba(var(--ds-red-rgb), 0.1) 100%
  );
  --ds-gradient-brand-on-dark: linear-gradient(
    135deg,
    #a5b4fc 0%,
    #c4b5fd 50%,
    #fca5a5 100%
  );
  /* Blue→purple two-stop diagonal shared by every icon tile and by the
     gradient-clipped metric numerals. The 180deg rails (progress/nav
     spines) stay literal — their angle is geometric, not brand. */
  --ds-gradient-icon-tile: linear-gradient(
    135deg,
    var(--ds-blue) 0%,
    var(--ds-purple) 100%
  );

  /* Borders (blue-tinted) */
  --ds-border-subtle: rgba(var(--ds-blue-rgb), 0.08);
  --ds-border: rgba(var(--ds-blue-rgb), 0.12);
  --ds-border-strong: rgba(var(--ds-blue-rgb), 0.22);

  /* Typography */
  --ds-font-display: "Plus Jakarta Sans", system-ui, -apple-system, sans-serif;
  --ds-font-mono: "JetBrains Mono", "SF Mono", Consolas, monospace;

  --ds-text-hero-dramatic: clamp(44px, 6vw, 64px);
  --ds-text-hero-standard: clamp(34px, 4.5vw, 48px);
  --ds-text-section: clamp(28px, 3.2vw, 40px);
  --ds-text-subsection: clamp(18px, 1.6vw, 22px);
  --ds-text-body: 16px;
  --ds-text-body-sm: 14px;
  --ds-text-caption: 12px;
  --ds-text-eyebrow: 11px;

  --ds-lh-tight: 1.1;
  --ds-lh-base: 1.5;
  --ds-lh-prose: 1.65;

  --ds-fw-regular: 400;
  --ds-fw-medium: 500;
  --ds-fw-semi: 600;
  --ds-fw-bold: 700;
  --ds-fw-black: 800;

  --ds-tracking-tight: -0.02em;
  --ds-tracking-base: 0;
  --ds-tracking-eyebrow: 0.14em;

  /* Chrome */
  --ds-site-header-h: 80px;

  /* Radius */
  --ds-radius-xs: 6px;
  --ds-radius-sm: 10px;
  --ds-radius-md: 14px;
  --ds-radius-lg: 20px;
  --ds-radius-full: 9999px;

  /* Shadows */
  --ds-shadow-sm: 0 1px 2px rgba(var(--ds-blue-rgb), 0.04);
  --ds-shadow-md:
    0 2px 6px rgba(var(--ds-blue-rgb), 0.05),
    0 8px 20px rgba(var(--ds-blue-rgb), 0.06);
  --ds-shadow-lg:
    0 8px 16px rgba(var(--ds-blue-rgb), 0.1),
    0 24px 48px rgba(var(--ds-blue-rgb), 0.12);
  --ds-shadow-gradient: 0 12px 24px rgba(var(--ds-blue-rgb), 0.12);
  /* Icon-tile resting elevation — the blue→purple gradient glyph squares
     share this single value; the -lg variant carries the larger 24px blur
     used by the bigger plan-status and hero-stat tiles. */
  --ds-shadow-icon-tile: 0 10px 20px rgba(var(--ds-blue-rgb), 0.25);
  --ds-shadow-icon-tile-lg: 0 10px 24px rgba(var(--ds-blue-rgb), 0.25);
  /* Focus rings. The inner 3px band is an OPAQUE brand tone so the ring
     itself clears the WCAG 1.4.11 3:1 floor against the white page
     (--ds-blue on white = 7.5:1); the outer 16% halo is decorative only
     and merely preserves the previous visual softness. Never reduce the
     opaque band to a translucent tint — that was the 1.30:1 regression. */
  --ds-shadow-focus:
    0 0 0 3px var(--ds-blue), 0 0 0 6px rgba(var(--ds-blue-rgb), 0.16);
  /* Same ring for controls whose own fill is brand blue (primary buttons):
     an inset white band separates the control from the blue ring so the
     indicator stays visible on a blue ground. */
  --ds-shadow-focus-on-brand:
    inset 0 0 0 2px var(--ds-white), 0 0 0 3px var(--ds-blue),
    0 0 0 6px rgba(var(--ds-blue-rgb), 0.16);
  --ds-shadow-focus-on-danger:
    inset 0 0 0 2px var(--ds-white), 0 0 0 3px var(--ds-danger),
    0 0 0 6px rgba(var(--ds-danger-rgb), 0.16);

  /* Motion */
  --ds-dur-fast: 150ms;
  --ds-dur-base: 300ms;
  --ds-dur-slow: 500ms;
  --ds-dur-hero: 900ms;

  --ds-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ds-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ds-ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ds-ease-back: cubic-bezier(0.68, -0.55, 0.27, 1.55);

  /* Spacing (4px rhythm). The `-N-5` half steps below 20px are deliberate:
     component-internal padding (button, badge, chip, input) lives between
     the whole steps, and a scale that omits them forces every small
     component off-scale by construction. Naming follows the widespread
     half-step convention (0-5 = 2px, 1-5 = 6px, …). Layout rhythm still
     uses the whole steps only. */
  --ds-space-0-5: 2px;
  --ds-space-1: 4px;
  --ds-space-1-5: 6px;
  --ds-space-2: 8px;
  --ds-space-2-5: 10px;
  --ds-space-3: 12px;
  --ds-space-3-5: 14px;
  --ds-space-4: 16px;
  --ds-space-4-5: 18px;
  --ds-space-5: 20px;
  --ds-space-6: 24px;
  --ds-space-8: 32px;
  --ds-space-10: 40px;
  --ds-space-12: 48px;
  --ds-space-16: 64px;
  --ds-space-20: 80px;
  --ds-space-24: 96px;

  /* ========================================================================
     * Promoted canonical tokens. These carry values that originated in the
     * former legacy namespace (tonal ramps, RGB channels, dark-surface scale,
     * decorative patterns, z-index, card and editorial type tokens) and now
     * hold their literals directly in the --ds-* namespace.
     * ====================================================================== */

  /* Blue tonal ramp + RGB channels (for rgba() composition) */
  --ds-blue-dark: #053a8a;
  --ds-blue-light: #2563d4;
  --ds-blue-rgb: 7, 78, 185;
  /* Two lighter blues used exclusively on dark marketing surfaces, where
     --ds-blue would read as near-black: -glow drives the ambient glows and
     conic sweeps (#5b8def), -on-dark the readable text/border accents
     (#7caeff). Declared as channels so every use runs through rgba(). */
  --ds-blue-glow-rgb: 91, 141, 239;
  --ds-blue-on-dark-rgb: 124, 174, 255;
  --ds-red-rgb: 233, 64, 55;
  --ds-purple-rgb: 114, 74, 222;
  --ds-ink-rgb: 37, 40, 64;

  /* Extra brand shades */
  --ds-purple-light: #a855f7;
  --ds-gold: #f5a623;

  /* Ink extras */
  --ds-ink-dim: #94a3b8;
  --ds-ink-xstrong: #05060a;

  /* Neutrals (universal, non-brand) + their RGB channels for rgba() */
  --ds-white: #ffffff;
  --ds-black: #000000;
  --ds-white-rgb: 255, 255, 255;
  --ds-black-rgb: 0, 0, 0;
  --ds-success-bright-rgb: 34, 197, 94;
  --ds-success-rgb: 7, 122, 61;
  --ds-info-rgb: 29, 78, 216;
  --ds-warn-rgb: 180, 83, 9;

  /* Solid border + extra surfaces */
  --ds-border-gray: #e4e7ee;
  --ds-surface-3: #e4e7ee;
  --ds-surface-4: #cbd5e1;
  --ds-surface-tint-red: rgba(var(--ds-red-rgb), 0.04);
  --ds-surface-tint-purple: rgba(var(--ds-purple-rgb), 0.04);
  --ds-surface-tint-blue: rgba(var(--ds-blue-rgb), 0.04);

  /* Dark surfaces */
  --ds-surface-dark-3: #1a2248;
  --ds-surface-dark-border: rgba(var(--ds-white-rgb), 0.1);

  /* Ink on dark surfaces */
  --ds-ink-on-dark-strong: #e9edff;
  --ds-ink-on-dark-body: #d2d8f0;
  --ds-ink-on-dark-muted: #97a1c9;
  --ds-ink-on-dark-subtle: #7985b0;
  --ds-ink-on-dark-accent: #7aa7ff;

  /* Typography extras (editorial sizes between body and subsection) */
  --ds-text-lead: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  --ds-text-lg: 1.125rem;
  --ds-text-title-3: clamp(1.25rem, 1.05rem + 0.8vw, 1.625rem);
  --ds-tracking-meta: 0.08em;

  /* Z-index scale — the deliberate stacking order of every floating
       layer: consent banner < modal backdrop < modal/filter sheet < toast
       < onboarding tour. An open modal must never be painted over by the
       cookie banner. */
  --ds-z-base: 1;
  --ds-z-dropdown: 1000;
  --ds-z-sticky: 1020;
  --ds-z-fixed: 1030;
  --ds-z-consent: 1035;
  --ds-z-modal-backdrop: 1040;
  --ds-z-modal: 1050;
  --ds-z-toast: 1080;
  --ds-z-tour: 1090;

  /* Card component tokens */
  --ds-card-lift: -4px;
  --ds-card-transition:
    transform var(--ds-dur-base) var(--ds-ease-standard),
    box-shadow var(--ds-dur-base) var(--ds-ease-standard),
    border-color var(--ds-dur-fast) var(--ds-ease-standard);

  /* Floating-card shadows (marketing cards in active/open states) */
  --ds-shadow-float: 0 12px 32px rgba(var(--ds-blue-rgb), 0.08);
  /* Primary-button hover shadow — deep-blue glow under the solid hover fill. */
  --ds-shadow-primary-hover: 0 10px 24px rgba(5, 53, 128, 0.35);
  /* Status focus rings — one canonical family aligned to --ds-shadow-focus
       (opaque 3px band + 16% halo). Danger covers invalid form controls +
       the danger button; success covers the valid/success form state. All
       three draw from the brand palette so the ring width and saturation
       never drift between focus states, and each opaque band clears 3:1
       against white (--ds-danger 5.41:1, --ds-success 5.44:1). */
  --ds-shadow-focus-danger:
    0 0 0 3px var(--ds-danger), 0 0 0 6px rgba(var(--ds-danger-rgb), 0.16);
  --ds-shadow-focus-success:
    0 0 0 3px var(--ds-success), 0 0 0 6px rgba(var(--ds-success-rgb), 0.16);
  /* Persistent field-validation halos. The states above are focus rings and
       vanish with the focus; .ls-field-invalid / .ls-field-valid and the
       server-rendered .is-invalid stay on the control after blur, so they use
       the soft tint instead — the opaque band is reserved for :focus-visible
       and would otherwise sit permanently on every filled-in field. */
  --ds-shadow-field-danger: 0 0 0 4px rgba(var(--ds-danger-rgb), 0.16);
  --ds-shadow-field-success: 0 0 0 4px rgba(var(--ds-success-rgb), 0.16);

  /* Status accents on dark surfaces (toast icons, on-dark badges) —
       lighter pastel counterparts of the AA status palette. */
  --ds-success-on-dark: #4ade80;
  --ds-danger-on-dark: #fca5a5;
  --ds-warn-on-dark: #fcd34d;
  --ds-info-on-dark: #93c5fd;

  /* Solid pastel tint pairs for ds-badge (bg + text per status). */
  --ds-neutral-tint-bg: #e6ecf7;
  --ds-neutral-tint-text: #054080;
  --ds-success-tint-bg: #d7efe0;
  --ds-success-tint-text: #045d2b;
  --ds-warn-tint-bg: #f5e7d0;
  --ds-warn-tint-text: #8a4209;
  --ds-danger-tint-bg: #f6d7d4;
  --ds-danger-tint-text: #a01e18;
  --ds-info-tint-bg: #dce5f5;
  --ds-info-tint-text: #143fa3;

  /* Amber accent (sticky-CTA star, rating glyphs) + bright amber channel
       used for warning tints on dark surfaces. */
  --ds-amber: #fbbf24;
  --ds-warn-bright-rgb: 245, 158, 11;

  /* Deep status inks for alert text on tinted alert backgrounds (AAA-ish). */
  --ds-success-deep: #0c6c44;
  --ds-warn-deep: #6b3e0a;
  --ds-danger-deep: #8a1d15;

  /* Deep brand blue — primary button hover fill (white text ≈ 9.6:1). */
  --ds-blue-deep: #053580;
  /* Bright danger — danger button hover fill. */
  --ds-danger-bright: #dc2626;
  --ds-danger-bright-rgb: 239, 68, 68;

  /* Toast / tour / tooltip / modal dark-glass shadows. */
  --ds-shadow-toast: 0 16px 36px rgba(7, 20, 55, 0.28);
  --ds-shadow-modal: 0 24px 56px rgba(7, 14, 33, 0.25);
  --ds-shadow-tour: 0 22px 48px rgba(7, 20, 55, 0.3);
  --ds-shadow-tooltip: 0 8px 18px rgba(15, 20, 45, 0.25);
  /* Danger-button hover glow. */
  --ds-shadow-danger-hover: 0 6px 16px rgba(var(--ds-danger-bright-rgb), 0.25);

  /* Indigo accents used on dark surfaces (eyebrow text, footer chips). */
  --ds-lavender: #a5b4fc;
  --ds-lavender-light: #c4b5fd;
  /* Violet end-stop of the signature dark-band gradient (hero, CTA band). */
  --ds-surface-dark-violet: #1a1035;

  /* Glass-pill shadows (ds-eyebrow signature frame). */
  --ds-shadow-pill:
    0 1px 0 rgba(var(--ds-white-rgb), 0.6) inset,
    0 2px 8px rgba(var(--ds-blue-rgb), 0.06);
  --ds-shadow-pill-on-dark:
    0 1px 0 rgba(var(--ds-white-rgb), 0.05) inset,
    0 8px 24px rgba(var(--ds-black-rgb), 0.25);

  /* Danger RGB channel for rgba() composition (wallet pulse, danger glows). */
  --ds-danger-rgb: 201, 45, 36;

  /* Dimming backdrop behind modals, tour steps and drawers. */
  --ds-backdrop: rgba(15, 20, 45, 0.55);

  /* App sidebar geometry (3-tier collapse behavior). */
  --ds-sidebar-width: 240px;
  --ds-sidebar-width-collapsed: 64px;
}

/* === Base / Reset === */
* {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
}
section[id] {
  scroll-margin-top: 80px;
}

/* Safety net against accidental horizontal scroll on mobile from oversized
   decorative layers (glow orbs, hero gradients, etc.). `clip` is preferred
   over `hidden` because it does not establish a scroll container and so
   does not break `position: sticky` ancestors. */
html,
body {
  overflow-x: clip;
}

body {
  font-family: var(--ds-font-display);
  color: var(--ds-ink);
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-prose);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--ds-white);
}

a {
  color: var(--ds-blue);
  text-decoration: none;
  transition: color var(--ds-dur-fast) var(--ds-ease-standard);
}
a:hover {
  color: var(--ds-blue-dark);
}

::selection {
  background: rgba(var(--ds-blue-rgb), 0.18);
  color: var(--ds-ink);
}

/* === Typography === */
/* Heading fallback ramp — components override these with their own classed
   sizes (ds-section__title, ds-hero__title, ds-prose…); the fallback maps
   onto the fluid type tokens. line-height 1.2 sits deliberately between
   --ds-lh-tight (display) and --ds-lh-base (copy) for unclassed headings. */
h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
  font-family: var(--ds-font-display);
  color: var(--ds-ink);
  font-weight: var(--ds-fw-bold);
  line-height: 1.2;
  margin-bottom: 1rem;
  letter-spacing: -0.01em;
}
h1,
.h1 {
  font-size: var(--ds-text-section);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-tight);
}
h2,
.h2 {
  font-size: var(--ds-text-title-3);
  font-weight: var(--ds-fw-bold);
  letter-spacing: -0.015em;
}
h3,
.h3 {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
}
h4,
.h4 {
  font-size: var(--ds-text-lg);
  font-weight: var(--ds-fw-semi);
}
h5,
.h5 {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-semi);
}
h6,
.h6 {
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
}

/* Spinning */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Shake */
@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }
  25%,
  75% {
    transform: translateX(-5px);
  }
  50% {
    transform: translateX(5px);
  }
}

/* === Forms — the ONE sanctioned crispy bridge ===
   Crispy renders Bootstrap form classes (.form-control/.form-select); this
   bridge restyles them to the exact computed values of the canonical
   .ds-form-control so crispy output is visually indistinguishable from
   hand-written ds-form markup. Keep both definitions in sync. */
.form-control,
.form-select {
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm);
  padding: var(--ds-space-2-5) var(--ds-space-3-5);
  font-size: var(--ds-text-body);
  line-height: 1.4;
  /* background-color (not the shorthand) — .form-select carries Bootstrap's
       chevron as a background-image that must survive this restyle. */
  background-color: var(--ds-surface);
  color: var(--ds-ink);
  transition:
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-fast) var(--ds-ease-out);
}
.form-control:focus,
.form-select:focus {
  border-color: var(--ds-blue);
  box-shadow: var(--ds-shadow-focus);
  outline: none;
}
/* Disabled parity with .ds-form-control:disabled — without it a crispy-
   rendered disabled field looked fully enabled next to a hand-written one. */
.form-control:disabled,
.form-select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: var(--ds-surface-tint);
}
/* Error parity with .ds-form-control--error. The shake is the one deliberate
   difference: this class arrives with a server-rendered response, where the
   nudge points at the field that was rejected. The --error modifier is set
   live while typing, where a shake on every keystroke would be punishing. */
.form-control.is-invalid,
.form-select.is-invalid {
  border-color: var(--ds-danger);
  background-color: var(--ds-danger-tint);
  box-shadow: var(--ds-shadow-field-danger);
  animation: shake var(--ds-dur-fast) ease-in-out;
}
.form-control.is-invalid:focus-visible,
.form-select.is-invalid:focus-visible {
  box-shadow: var(--ds-shadow-focus-danger);
}
/* Select chevron — the ds-form-control/.form-select background fills would
   otherwise erase Bootstrap's arrow. The element-qualified selectors outrank
   both base classes regardless of source order. */
select.form-select,
select.form-control,
select.ds-form-control {
  padding-right: 36px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23252840' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 14px 14px;
  appearance: none;
  -webkit-appearance: none;
}
.form-control::placeholder {
  color: var(--ds-ink-mute);
}
.form-label {
  font-weight: var(--ds-fw-medium);
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink);
  margin-bottom: 0.4rem;
}
.form-text {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
}
.form-check-input {
  border: 1px solid var(--ds-surface-3);
}
.form-check-input:checked {
  background-color: var(--ds-blue);
  border-color: var(--ds-blue);
}
.form-check-input:focus {
  box-shadow: var(--ds-shadow-focus);
  border-color: var(--ds-blue);
}

/* === Blog === */
.blog-card {
  color: var(--ds-ink);
  background: var(--ds-surface);
  border: 1px solid var(--ds-surface-3);
  border-radius: var(--ds-radius-sm);
  overflow: hidden;
  height: 100%;
  transition:
    border-color var(--ds-dur-fast) var(--ds-ease-standard),
    box-shadow var(--ds-dur-base) var(--ds-ease-standard),
    transform var(--ds-dur-base) var(--ds-ease-standard);
  display: flex;
  flex-direction: column;
  box-shadow: var(--ds-shadow-sm);
}
.blog-card:hover {
  color: var(--ds-ink);
  transform: translateY(-1px);
  border-color: rgba(var(--ds-blue-rgb), 0.25);
  box-shadow: var(--ds-shadow-md);
}
/* Cluster pill on blog cards — pure layout modifier on ds-badge--neutral.
   align-self stops the flex-column card from stretching the inline badge to
   full card width; the badge skin itself stays canonical. */
.blog-card .badge-cluster {
  align-self: flex-start;
  margin-bottom: 0.75rem;
}
.blog-card h2,
.blog-card h3 {
  color: var(--ds-ink);
  font-size: var(--ds-text-lg);
  font-weight: var(--ds-fw-bold);
  margin-bottom: 0.5rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.blog-card .excerpt {
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  line-height: 1.55;
  flex-grow: 1;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.blog-card .meta {
  display: flex;
  gap: 1rem;
  align-items: center;
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--ds-surface-3);
}

.ds-prose.blog-article {
  font-size: 1.0625rem;
  line-height: 1.7;
}
.blog-article h1 {
  margin-bottom: 1.5rem;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
}
.ds-prose.blog-article h2 {
  margin-top: 2.75rem;
  margin-bottom: 1rem;
  font-size: 1.5rem;
}
.ds-prose.blog-article h3 {
  margin-top: 1.75rem;
  font-size: 1.25rem;
}
.blog-article p {
  margin-bottom: 1rem;
}
.blog-article ul,
.blog-article ol {
  margin-bottom: 1.25rem;
  padding-left: 1.25rem;
}
.blog-article ul li,
.blog-article ol li {
  margin-bottom: 0.4rem;
}
.blog-article a {
  color: var(--ds-blue);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.blog-article a:hover {
  color: var(--ds-blue-dark);
}
.blog-article blockquote {
  border-left: 4px solid var(--ds-blue);
  padding: 1rem 1.25rem;
  background: rgba(var(--ds-blue-rgb), 0.04);
  margin: 1.5rem 0;
  font-style: italic;
}
.key-takeaways {
  background: rgba(var(--ds-blue-rgb), 0.05);
  border-left: 4px solid var(--ds-blue);
  padding: 1.25rem 1.5rem;
  border-radius: var(--ds-radius-sm);
  margin: 1.75rem 0 2rem;
}
.ds-prose .key-takeaways h2 {
  font-size: 1.05rem;
  color: var(--ds-blue);
  margin-top: 0;
  margin-bottom: 0.75rem;
}
.key-takeaways ul {
  margin: 0;
  padding-left: 1.25rem;
}

/* === Tables === */
.table {
  --bs-table-color: var(--ds-ink);
  border-collapse: separate;
  border-spacing: 0;
}
.table thead th {
  background: var(--ds-surface-tint);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-caption);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--ds-fw-bold);
  border-bottom: 1px solid var(--ds-surface-3);
  padding: 0.85rem 1rem;
}
.table tbody td {
  padding: 0.85rem 1rem;
  border-color: var(--ds-surface-3);
  vertical-align: middle;
}

/* ds-table is the canonical DS alias for Bootstrap .table. Inherits the
   same overrides defined on .table above via the comma selector below. */
.ds-table {
  --bs-table-color: var(--ds-ink);
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}
.ds-table thead th {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.04),
    rgba(var(--ds-purple-rgb), 0.03)
  );
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-caption);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--ds-fw-bold);
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  padding: 0.85rem 1rem;
}
.ds-table tbody td {
  padding: 0.85rem 1rem;
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.06);
  vertical-align: middle;
}
.ds-table tbody tr {
  transition: background var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-table tbody tr:hover {
  background: rgba(var(--ds-blue-rgb), 0.02);
}
.ds-table tbody tr:last-child td {
  border-bottom: 0;
}

/* Removes the default table margin when the table sits directly inside a
   card body that already handles spacing. */
.ds-table--flush {
  margin: 0;
}

/* Right-align a column header in data tables (e.g. numeric columns). */
.ds-col--right {
  text-align: right;
}

/* Numeric data column — right-aligned with fixed-width digits to keep
   values visually aligned across rows. */
.ds-col--numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Canonical DS wrapper for data tables — provides the border-radius, scroll
   container, and box-shadow that were previously on .data-table-wrap. */
.ds-table-wrap {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  overflow: auto;
  box-shadow: var(--ds-shadow-sm);
}

/* Compact column for row action buttons (download, retry). Sits mid-table
   right after the status column so the primary action stays visible first
   when the table scrolls horizontally on small screens (C3.2). */
.ds-table__actions-cell {
  width: 80px;
  white-space: nowrap;
}

/* Fixed-width, centred column for row-selection checkboxes. */
.ds-lead-table__row-select {
  width: 40px;
  padding-inline: 8px;
  text-align: center;
}

/* Token-mapped spacing utilities for elements that need a single margin-top
   override without a bespoke block selector. */
.ds-mt-3 {
  margin-top: var(--ds-space-3);
}
.ds-mt-8 {
  margin-top: var(--ds-space-8);
}

/* === Alerts === */
.alert {
  border: 1px solid transparent;
  border-radius: var(--ds-radius-sm);
  padding: 0.85rem 1rem;
  font-size: var(--ds-text-body-sm);
}
.alert-info {
  background: rgba(var(--ds-blue-rgb), 0.08);
  color: var(--ds-blue-dark);
  border-color: rgba(var(--ds-blue-rgb), 0.25);
}

/* === Skip-Link === */
.skip-link {
  position: absolute;
  top: -100px;
  left: 0;
  background: var(--ds-ink);
  color: var(--ds-white);
  padding: var(--ds-space-3) var(--ds-space-5);
  /* Above the whole z-ramp on purpose: the skip link is the keyboard user's
     escape hatch and must stay reachable even with a modal or toast open. */
  z-index: 9999;
  border-radius: 0 0 var(--ds-radius-sm) 0;
}
.skip-link:focus {
  top: 0;
  color: var(--ds-white);
}

/* === Reduced Motion ===
   Global fallback: freeze all animations/transitions for motion-sensitive users.
   Exception: gentle decorative signature-motion (particles, beams, orb glow, gradient
   shift) is kept because its linear, slow drift is not a vestibular hazard — it is
   part of the brand identity and safer than hazardous motion like parallax or 3D rotations. */
/* === Lazy-Loaded Images === */
img[loading="lazy"] {
  transition: opacity 0.4s ease-in;
}
img {
  max-width: 100%;
  height: auto;
}

/* Breadcrumb navigation strip — small muted text row above hero headlines.
   Replaces the Bootstrap .small + .text-muted + .mb-3 combination. */
.ds-breadcrumb {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  margin-bottom: 0.75rem;
}
.ds-breadcrumb a {
  color: var(--ds-ink-soft);
  text-decoration: none;
}
.ds-breadcrumb a:hover {
  color: var(--ds-ink);
  text-decoration: underline;
}

/* === Blog Cluster Chips (blog_index.html filter row) === */
.cluster-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
  margin: var(--ds-space-6) 0 var(--ds-space-6);
}
.cluster-chip {
  padding: var(--ds-space-1-5) var(--ds-space-3-5);
  background: var(--ds-surface-muted);
  color: var(--ds-ink);
  border-radius: var(--ds-radius-full);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-medium);
  text-decoration: none;
  transition:
    background-color var(--ds-dur-fast) var(--ds-ease-standard),
    color var(--ds-dur-fast) var(--ds-ease-standard);
  display: inline-block;
}
.cluster-chip:hover {
  background: var(--ds-surface-3);
  color: var(--ds-ink);
}
.cluster-chip.is-active {
  background: var(--ds-blue);
  color: var(--ds-white);
}
.cluster-chip.is-active:hover {
  background: var(--ds-blue-dark);
  color: var(--ds-white);
}
.cluster-chip:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* ============================================================
   ONE-PAGER HOME — Premium redesign (2026-04-19)
   Classes use the .ds-op- prefix within the .ds- design system.
   ============================================================ */

.container {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 var(--ds-space-6);
}

.ds-gradient-text,
.ds-gradient-text .word,
.ds-gradient-text .char {
  background: var(--ds-gradient-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* When SplitType wraps the phrase in per-character spans for the reveal
   animation, motion.js rewrites each character's background-size and
   background-position so every glyph shows its slice of one continuous
   blue-to-red sweep across the whole word (see applyContinuousGradient).
   Without JS this rule still renders a visible per-character gradient, so the
   wordmark degrades gracefully. The background must therefore span the word,
   not repeat per glyph. */
.ds-gradient-text .char {
  background-repeat: no-repeat;
}

/* Section eyebrow — reuses the .ds-app-eyebrow look from the
   dashboard (small pulsing green dot + uppercase category label) so
   the marketing site and the authenticated app share one visual
   signature. Icon-led eyebrows (e.g. .ds-eyebrow on pricing
   add-on heads) opt out of the dot. */

.ds-card__icon {
  width: 48px;
  height: 48px;
  border-radius: var(--ds-radius-sm);
  background: var(--ds-gradient-brand);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ds-white);
  font-size: 22px;
  margin-bottom: var(--ds-space-5);
  transition:
    transform 0.4s var(--ds-ease-out),
    box-shadow 0.4s var(--ds-ease-out);
  box-shadow: 0 6px 16px rgba(var(--ds-red-rgb), 0.2);
}

.ds-op-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}

.ds-op-orb-blue {
  background: radial-gradient(
    circle,
    rgba(var(--ds-blue-rgb), 0.15) 0%,
    rgba(var(--ds-blue-rgb), 0) 70%
  );
}

.ds-op-orb-purple {
  background: radial-gradient(
    circle,
    rgba(var(--ds-purple-rgb), 0.15) 0%,
    rgba(var(--ds-purple-rgb), 0) 70%
  );
}

/* Canonical hero-orb size+position modifiers — eliminate per-template inline styles.
   Applied to .ds-op-orb elements in all marketing hero sections. */
.ds-op-orb--hero-blue {
  top: -10%;
  left: -8%;
  width: 420px;
  height: 420px;
}

.ds-op-orb--hero-purple {
  bottom: -20%;
  right: -8%;
  width: 380px;
  height: 380px;
}

/* Width modifiers carry doubled specificity so they always beat the
   .ds-section__inner base (max-width 1200px, defined at the Phase-2
   component home) regardless of source order. */
.ds-section__inner.ds-section__inner--centered {
  text-align: center;
}

/* Centered hero-inner with the default 760 px cap — mirrors the most common
   marketing hero pattern (blog index, contact). Combines margin + center
   alignment in one modifier rather than two classes. */
.ds-section__inner.ds-section__inner--hero {
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
}

/* Prose article hero — wider 820 px cap for breadcrumb nav and hero content
   in blog_article.html. */
.ds-section__inner.ds-section__inner--article {
  max-width: 820px;
  margin: 0 auto;
  text-align: center;
}

/* Long-form text columns — blog article bodies (prose-body) and the legal
   pages (impressum, datenschutz, agb, widerruf). Deliberately uncapped:
   running text takes the full width of the section column (the 1200 px
   .ds-section__inner base), and the distance to the edge comes from the
   section padding alone. A reading-width cap left a wide empty strip beside
   every paragraph while the tables next to it ran to the edge.
   tests/test_design_gates.py keeps any max-width off these columns and off
   prose paragraphs, lists and headings. */
.ds-section__inner.ds-section__inner--prose-body,
.ds-section__inner.ds-section__inner--legal {
  margin: 0 auto;
}

/* Narrow panel — 560 px cap for single-focus confirmation/empty-state layouts. */
.ds-section__inner.ds-section__inner--narrow {
  max-width: 560px;
  margin: 0 auto;
}

/* Section variant that vertically centers its content within a 60 vh minimum
   height (used on the contact-thanks single-state screen). */
.ds-section--vh60 {
  min-height: 60vh;
  display: flex;
  align-items: center;
}

/* Error pages: the layout-shell body is flex:1 — let the single section
   absorb that height and center its content so no dead band remains
   between the tinted section and the footer at tall viewports. */
.ds-section--fill {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Error pages (the only users of .ds-section--fill) place the status badge
   directly above the headline. Give the badge breathing room so it does not
   crowd the title — applies to every error/status page at once. */
.ds-section--fill .ds-eyebrow {
  margin-bottom: var(--ds-space-3);
}

.ds-section__inner .ds-section__lead {
  margin-left: auto;
  margin-right: auto;
}

/* Button row used inside .ds-section__inner for error pages and other
   centered CTA layouts. Token-based gap, wraps on narrow viewports. */
.ds-button-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--ds-space-3, 0.75rem);
  margin-top: var(--ds-space-4, 1rem);
}

/* Single-column FAQ stack — blog articles render their FAQ accordion
   inside the prose column; the landing page uses .ds-faq-grid instead. */
.ds-faq-stack {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  margin-top: var(--ds-space-6);
}

.ds-op-faq-item {
  background: var(--ds-white);
  border: 1px solid var(--ds-surface-muted);
  border-radius: var(--ds-radius-md);
  overflow: hidden;
  transition: all 0.3s var(--ds-ease-out);
}

.ds-op-faq-item.is-open {
  border-color: rgba(var(--ds-red-rgb), 0.2);
  box-shadow: var(--ds-shadow-float);
  background: linear-gradient(
    180deg,
    var(--ds-white) 0%,
    var(--ds-surface-tint) 100%
  );
}

.ds-op-faq-question {
  width: 100%;
  background: transparent;
  border: none;
  padding: var(--ds-space-5) var(--ds-space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  text-align: left;
  font-size: 17px;
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  cursor: pointer;
}

.ds-op-faq-icon {
  color: var(--ds-blue);
  font-size: var(--ds-text-lg);
  transition: transform 0.3s var(--ds-ease-out);
  flex-shrink: 0;
}

.ds-op-faq-item.is-open .ds-op-faq-icon {
  transform: rotate(45deg);
}

.ds-op-faq-answer {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s var(--ds-ease-out);
}

.ds-op-faq-answer p {
  padding: 0 24px 22px;
  margin: 0;
  font-size: 15px;
  line-height: var(--ds-lh-prose);
  color: var(--ds-ink-mute);
}

/* --- Focus visible states for one-pager interactive elements --- */
.ds-op-faq-question:focus-visible {
  outline: 3px solid var(--ds-blue);
  outline-offset: 3px;
}
.ds-op-faq-question:hover {
  background: rgba(var(--ds-blue-rgb), 0.035);
}

/* ============================================================
   P1.C — Polish Pass: refined shadows, micro-animations,
   shimmer effects, mobile footer fix
   ============================================================ */

/* ============================================================
   P1.G — Graphics, badges, decorative patterns
   ============================================================ */

/* Decorative SVG patterns positioned at section corners */
.ds-op-pattern-dots {
  position: absolute;
  pointer-events: none;
  z-index: 0;
  opacity: 0.8;
}

.ds-op-pattern-dots-tl {
  top: 60px;
  left: 24px;
}

.ds-op-pattern-dots-hero {
  bottom: 40px;
  right: 60px;
  width: 180px;
  height: 180px;
}

/* Dot colour of the hero variant — identical on every marketing hero, so it
   belongs to the token scale rather than to each page's SVG markup. */
.ds-op-pattern-dots-hero circle {
  fill: rgba(var(--ds-blue-rgb), 0.18);
}

@media (max-width: 767px) {
  .ds-op-pattern-dots {
    display: none;
  }
}
/* Pricing-card tier category tag — uniform height {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  height: 26px;
  padding: 0 var(--ds-space-3-5);
  border-radius: var(--ds-radius-full);
  font-size: 10px;
  font-weight: var(--ds-fw-black);
  line-height: 1;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin: 0 0 var(--ds-space-3-5) 0;
  color: var(--ds-white);
  white-space: nowrap;
}

/* Sparkle decorations (quote section) */
.ds-op-pattern-sparkle {
  position: absolute;
  pointer-events: none;
  z-index: 0;
  opacity: 0.9;
  animation: opSparkleTwinkle 3s ease-in-out infinite;
}

.ds-op-pattern-sparkle-tl {
  top: 60px;
  left: 40px;
}
.ds-op-pattern-sparkle-br {
  bottom: 80px;
  right: 60px;
  animation-delay: 1.2s;
}

/* The bottom-right sparkle is always the red accent. The top-left one varies
   per page (blue, red, different alphas) and therefore stays in the markup. */
.ds-op-pattern-sparkle-br g {
  fill: rgba(var(--ds-red-rgb), 0.32);
}

@keyframes opSparkleTwinkle {
  0%,
  100% {
    opacity: 0.4;
    transform: scale(0.9) rotate(0deg);
  }
  50% {
    opacity: 1;
    transform: scale(1.05) rotate(10deg);
  }
}

@media (max-width: 767px) {
  .ds-op-pattern-sparkle {
    display: none;
  }
}

/* Hexagon pattern for FAQ section */
.ds-op-pattern-hexa {
  position: absolute;
  pointer-events: none;
  z-index: 0;
}

/* Outline colour of the hexagon cells — the same on all three legal pages. */
.ds-op-pattern-hexa path {
  stroke: rgba(var(--ds-blue-rgb), 0.14);
}

.ds-op-pattern-hexa-tl {
  top: 60px;
  left: 24px;
  opacity: 0.7;
}

/* Top-right hexa variant — mirrors the TL pattern to the right side.
   Used on the Widerruf page to visually distinguish it from other legal pages. */
.ds-op-pattern-hexa-tr {
  top: 60px;
  left: auto;
  right: 40px;
  opacity: 0.7;
}

@media (max-width: 767px) {
  .ds-op-pattern-hexa {
    display: none;
  }
}

/* ============================================================
   Block A — Design-System Unification
   Card shadows, eyebrow shape and headline typography unified
   across marketing, app and error surfaces. The former
   .btn.btn-primary gradient layer was deleted; every submit
   button (incl. the contact form) now renders through the
   ds-button ds-button--primary classes.
   ============================================================ */

/* --- Section-title typography consistency --- */
.ds-section__title {
  font-family: var(--ds-font-display);
} /* --- Subtitle typography consistency --- */
.ds-section__lead {
  font-family: var(--ds-font-display);
  font-weight: var(--ds-fw-regular);
}

/* ========================================================================
   Block B — UX-Polish additions (toasts, skeletons, empty-states,
   tooltips, form-validation, onboarding tour, htmx indicator).
   ======================================================================== */

/* === B1: Toast notifications =========================================== */
.ls-toast-container {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: var(--ds-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  max-width: 360px;
  width: calc(100vw - 40px);
  pointer-events: none;
}

.ls-toast {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-3);
  padding: var(--ds-space-3-5) var(--ds-space-4);
  background: rgba(var(--ds-ink-rgb), 0.96);
  color: var(--ds-white);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-toast);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(var(--ds-white-rgb), 0.06);
  overflow: hidden;
  pointer-events: auto;
  opacity: 0;
  transform: translateX(24px);
  transition:
    opacity 0.24s ease,
    transform 0.24s ease;
  font-family: var(--ds-font-display);
}

.ls-toast::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 4px;
  background: linear-gradient(180deg, var(--ds-blue), var(--ds-red));
}

.ls-toast-in {
  opacity: 1;
  transform: translateX(0);
}

.ls-toast-leaving {
  opacity: 0;
  transform: translateX(24px);
}

.ls-toast-icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--ds-radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
  background: rgba(var(--ds-white-rgb), 0.08);
  color: var(--ds-white);
}

.ls-toast-success .ls-toast-icon {
  background: rgba(var(--ds-success-bright-rgb), 0.22);
  color: var(--ds-success-on-dark);
}
.ls-toast-error .ls-toast-icon {
  background: rgba(var(--ds-red-rgb), 0.22);
  color: var(--ds-danger-on-dark);
}
.ls-toast-warning .ls-toast-icon {
  background: rgba(var(--ds-warn-bright-rgb), 0.22);
  color: var(--ds-warn-on-dark);
}
.ls-toast-info .ls-toast-icon {
  background: rgba(var(--ds-blue-rgb), 0.25);
  color: var(--ds-info-on-dark);
}

.ls-toast-body {
  flex: 1;
  min-width: 0;
  padding-top: var(--ds-space-1);
}

.ls-toast-message {
  display: block;
  font-size: var(--ds-text-body-sm);
  line-height: 1.45;
  color: rgba(var(--ds-white-rgb), 0.94);
  word-break: break-word;
}

.ls-toast-close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: 0;
  background: transparent;
  color: rgba(var(--ds-white-rgb), 0.55);
  border-radius: var(--ds-radius-xs);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--ds-text-lg);
  transition:
    background 0.18s,
    color 0.18s;
}

.ls-toast-close:hover {
  background: rgba(var(--ds-white-rgb), 0.08);
  color: var(--ds-white);
}

.ls-toast-close:focus-visible {
  background: rgba(var(--ds-white-rgb), 0.08);
  color: var(--ds-white);
  outline: none;
  box-shadow: 0 0 0 3px rgba(var(--ds-white-rgb), 0.35);
}

/* === B2: Skeleton loaders ============================================== */
.ls-skel {
  display: block;
  border-radius: var(--ds-radius-xs);
  background: linear-gradient(
    90deg,
    rgba(var(--ds-ink-rgb), 0.08) 0%,
    rgba(var(--ds-ink-rgb), 0.14) 50%,
    rgba(var(--ds-ink-rgb), 0.08) 100%
  );
  background-size: 200% 100%;
  animation: lsSkelShimmer 1.4s ease-in-out infinite;
}

.ls-skel-line {
  height: 12px;
  width: 100%;
}

/* HTMX live-count indicator — only visible during htmx-request. */
.ls-skel-count {
  display: none;
  margin-top: var(--ds-space-1);
  max-width: 160px;
}

.htmx-request .ls-skel-count,
.htmx-request.ls-skel-count {
  display: block;
}

@keyframes lsSkelShimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* === B3: Empty-state illustrations ===================================== */

/* === B4: Inline form validation ======================================== */
/* !important sanctioned: the JS-applied validation state must outrank the
   :focus border/shadow of every input system while the user is typing. */
.ls-field-invalid {
  border-color: var(--ds-danger) !important;
  box-shadow: var(--ds-shadow-field-danger) !important;
}

.ls-field-valid {
  border-color: var(--ds-success) !important;
  box-shadow: var(--ds-shadow-field-success) !important;
}

/* While the field has keyboard focus the opaque ring takes over again, so
   the state colour never costs the control its 3:1 focus indicator. */
.ls-field-invalid:focus-visible {
  box-shadow: var(--ds-shadow-focus-danger) !important;
}

.ls-field-valid:focus-visible {
  box-shadow: var(--ds-shadow-focus-success) !important;
}

.ls-field-error {
  display: flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  margin-top: var(--ds-space-1-5);
  color: var(--ds-danger);
  font-size: var(--ds-text-body-sm);
  line-height: 1.3;
}

.ls-field-error i {
  flex-shrink: 0;
  font-size: var(--ds-text-body);
}

.ls-field-ok {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ds-success);
  font-size: 1.05rem;
  pointer-events: none;
}

.ls-validate-wrap {
  position: relative;
  display: block;
}

/* === B5: Onboarding tour =============================================== */
.ls-tour-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--ds-z-tour);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.22s ease;
}

.ls-tour-overlay.ls-tour-leaving {
  opacity: 0;
}

.ls-tour-backdrop {
  position: absolute;
  inset: 0;
  background: var(--ds-backdrop);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  pointer-events: auto;
}

.ls-tour-highlight {
  position: absolute;
  border-radius: var(--ds-radius-md);
  box-shadow:
    0 0 0 4px rgba(var(--ds-white-rgb), 0.9),
    0 0 0 9999px var(--ds-backdrop);
  transition:
    top 0.25s ease,
    left 0.25s ease,
    width 0.25s ease,
    height 0.25s ease;
  pointer-events: none;
  display: none;
}

.ls-tour-tooltip {
  position: absolute;
  width: 360px;
  max-width: calc(100vw - 40px);
  padding: 22px 22px 18px;
  background: var(--ds-white);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-tour);
  pointer-events: auto;
  font-family: var(--ds-font-display);
  transition:
    top 0.25s ease,
    left 0.25s ease;
}

/* Overrides the JS-driven absolute top/left coordinates set per-step so the
   centered-mode tooltip lands at viewport mid-point regardless of scroll. */
.ls-tour-tooltip-center {
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
}

.ls-tour-step {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-blue);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin-bottom: var(--ds-space-2);
}

.ls-tour-title {
  margin: 0 0 var(--ds-space-2);
  font-size: 1.2rem;
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  letter-spacing: -0.01em;
}

.ls-tour-body {
  margin: 0 0 var(--ds-space-4-5);
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  line-height: var(--ds-lh-base);
}

.ls-tour-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--ds-space-3);
}

.ls-tour-skip {
  border: 0;
  background: transparent;
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-semi);
  font-size: var(--ds-text-body-sm);
  cursor: pointer;
  padding: var(--ds-space-2) var(--ds-space-3);
  border-radius: var(--ds-radius-xs);
  transition:
    background 0.18s,
    color 0.18s;
}

.ls-tour-skip:hover,
.ls-tour-skip:focus {
  background: rgba(var(--ds-ink-rgb), 0.08);
  color: var(--ds-ink);
  outline: none;
}

/* The tour is a modal layer with a focus trap, so the ring is the only cue
   telling a keyboard user which of the two buttons is selected — the hover
   styling above is identical for both and cannot carry that job. */
.ls-tour-skip:focus-visible {
  box-shadow: var(--ds-shadow-focus);
}

.ls-tour-next {
  border: 0;
  padding: var(--ds-space-2-5) var(--ds-space-5);
  background: linear-gradient(135deg, var(--ds-blue) 0%, var(--ds-red) 100%);
  color: var(--ds-white);
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-body-sm);
  border-radius: var(--ds-radius-sm);
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(var(--ds-blue-rgb), 0.25);
  transition:
    transform 0.18s ease,
    box-shadow 0.18s ease;
}

.ls-tour-next:hover,
.ls-tour-next:focus {
  transform: translateY(-1px);
  box-shadow: 0 10px 20px rgba(var(--ds-blue-rgb), 0.3);
  outline: none;
}

/* Same reasoning as the skip button. The face carries the brand gradient, so
   the ring has to be the on-brand variant; the lift shadow is repeated because
   box-shadow does not merge across rules. */
.ls-tour-next:focus-visible {
  box-shadow:
    0 10px 20px rgba(var(--ds-blue-rgb), 0.3),
    var(--ds-shadow-focus-on-brand);
}

/* Cursor-follow glow layer. The element is created by motion.js
   (cursorFollowGlow) and appended to a dark container; only its opacity and
   GSAP transform are set from script, so the appearance stays token-driven
   here instead of in an inline style string. */
.ls-cursor-glow {
  position: absolute;
  top: 0;
  left: 0;
  width: 400px;
  height: 400px;
  margin: -200px 0 0 -200px;
  background: radial-gradient(
    circle,
    rgba(var(--ds-blue-glow-rgb), 0.25),
    transparent 60%
  );
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transition: opacity 300ms ease;
}

/* === B6: Tooltips ====================================================== */
.ls-tooltip {
  position: absolute;
  top: -9999px;
  left: -9999px;
  z-index: 1100;
  max-width: 240px;
  padding: var(--ds-space-2) var(--ds-space-3);
  background: var(--ds-ink);
  color: var(--ds-white);
  border-radius: var(--ds-radius-xs);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-medium);
  line-height: 1.4;
  font-family: var(--ds-font-display);
  box-shadow: var(--ds-shadow-tooltip);
  opacity: 0;
  transform: translateY(-2px);
  transition:
    opacity 0.16s ease,
    transform 0.16s ease;
  pointer-events: none;
  white-space: normal;
}

.ls-tooltip-visible {
  opacity: 1;
  transform: translateY(0);
}

[data-tooltip] {
  cursor: help;
}

[data-tooltip].btn,
[data-tooltip] button,
[data-tooltip] a {
  cursor: inherit;
}

/* === B7: HTMX loading indicator polish ================================= */
.htmx-request,
.htmx-request.htmx-request {
  opacity: 0.6;
  animation: lsHtmxPulse 1.2s ease-in-out infinite;
  transition: opacity 0.18s ease;
}

.htmx-indicator {
  opacity: 0;
  transition: opacity 0.18s ease;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

@keyframes lsHtmxPulse {
  0%,
  100% {
    opacity: 0.65;
  }
  50% {
    opacity: 0.92;
  }
}

/* ============================================================
   Dark Hero — reusable for /design/,
error pages,
CTAs
   Deep navy + blue/red gradient orbs + subtle grid pattern
   ============================================================ */

/* ============================================================
   GLOBAL CONSISTENCY PASS — applies the polish iteration (781a04d)
   across all surfaces,
.ds-op-faq-item,
.blog-card {
  transition:
    transform var(--ds-dur-slow) var(--ds-ease-out),
    box-shadow var(--ds-dur-slow) var(--ds-ease-out),
    border-color 0.4s ease,
    background-color 0.3s ease;
  will-change: transform;
}
/* --- Transitions: buttons in unification layer (btn.btn-primary etc) --- */
.ds-button.ds-button--primary {
  transition:
    transform var(--ds-dur-slow) var(--ds-ease-out),
    box-shadow var(--ds-dur-slow) var(--ds-ease-out),
    background-position 0.8s var(--ds-ease-out),
    border-color 0.4s ease,
    color 0.3s ease !important;
}
/* --- Badges: unify heights + kill margin-shifts globally --- */
.ds-eyebrow {
  white-space: nowrap;
  line-height: 1;
} /* Inline-flex on all pill-like elements so vertical-align never shifts */
.ds-eyebrow {
  flex-wrap: wrap;
  max-width: 100%;
}
/* --- Disabled form controls (globally; affects marketing + app + auth) */
input:disabled,
textarea:disabled,
select:disabled,
.form-control:disabled,
.form-select:disabled,
input[readonly],
textarea[readonly],
.form-control[readonly] {
  background-color: var(--ds-surface-tint);
  color: var(--ds-ink-mute);
  border-color: var(--ds-surface-3);
  cursor: not-allowed;
  opacity: 0.7;
  box-shadow: none;
}
/* Disabled state unification — generic fallback for non-ds buttons. */
button:disabled,
[type="submit"]:disabled {
  cursor: not-allowed;
  opacity: 0.55;
  pointer-events: none;
  box-shadow: none;
  transform: none;
}
/* --- Keyboard focus rings. Bootstrap & Crispy defaults are disabled in
       many places; this restores a consistent 3-px ring in brand blue.
       The colour is the OPAQUE --ds-blue (7.5:1 on white), never the
       translucent --ds-border-strong: that token composites to #c8d8ef and
       measures 1.44:1, far below the 3:1 that WCAG 1.4.11 requires of a
       focus indicator. Controls carrying their own --ds-shadow-focus ring
       were unaffected; every other link and button fell back to here and
       had, in practice, no visible focus at all. */
.blog-card:focus-visible,
.ds-op-faq-item:focus-visible {
  outline: 3px solid var(--ds-blue);
  outline-offset: 3px;
}
button:focus-visible,
[type="submit"]:focus-visible,
[type="button"]:focus-visible {
  outline: 3px solid var(--ds-blue);
  outline-offset: 3px;
}

a:focus-visible {
  outline: 2px solid var(--ds-blue);
  outline-offset: 2px;
  border-radius: var(--ds-radius-xs);
}

/* Same ring on dark surfaces, in the on-dark accent. Brand blue measures
   8.03:1 against the light page but only 2.55:1 against --ds-surface-dark,
   so the dark marketing sections and the full footer would sit below the
   3:1 floor of WCAG 1.4.11 on exactly the links that carry no ring of their
   own (footer columns, links inside dark bands). */
.ds-section--dark a:focus-visible,
.ds-section--dark-pattern a:focus-visible,
.ds-site-footer a:focus-visible,
.ds-cta-band a:focus-visible,
.ds-hero--dramatic a:focus-visible {
  outline-color: var(--ds-ink-on-dark-accent);
}

/* Table rows receive focus-within (users tab through embedded links) */
.table tbody tr:focus-within {
  background: var(--ds-surface-tint);
  outline: 2px solid var(--ds-blue);
  outline-offset: -2px;
}

/* ============================================================
   Utility classes — replace inline font-size/color overrides
   that were previously scattered across templates. Define once,
   reuse wherever a size/weight override is genuinely needed.
   ============================================================ */

/* Standardized icon size for alert / hint panels. */
.alert-icon-lg {
  font-size: 1.5rem;
  flex-shrink: 0;
}
/* ============================================================
   Standard card hover behaviour — centralises the lift + shadow
   transition so every card-like component benefits from the
   design-token --card-transition / --card-lift / --card-shadow-hover
   without each CSS block re-stating the same values.
   ============================================================ */
.blog-card,
.ds-op-faq-item {
  transition: var(--ds-card-transition);
}
.blog-card:hover {
  transform: translateY(var(--ds-card-lift));
  box-shadow: var(--ds-shadow-md);
}
/* Blog-card baseline colour — inherit ink so templates no longer
   need style="color:inherit". */

/* ============================================================
   Article metadata strip (blog article hero) — date / reading-time /
   pillar badge displayed as an icon-led row.
   ============================================================ */
.article-metadata {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(1rem, 3vw, 2rem);
  margin-top: 1.5rem;
  padding: 0.75rem 1.25rem;
  background: var(--ds-surface-tint);
  border-radius: var(--ds-radius-full);
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
}

.article-metadata-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  line-height: 1;
  white-space: nowrap;
}

.article-metadata-item > i {
  font-size: var(--ds-text-body);
  color: var(--ds-blue);
  opacity: 0.75;
}

.article-metadata-badge {
  padding: 0.25rem 0.7rem;
  border-radius: var(--ds-radius-full);
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  letter-spacing: 0.02em;
}

.article-metadata-badge > i {
  color: var(--ds-white);
  opacity: 1;
}

/* ============================================================
   Mobile polish — remaining responsive gaps flagged in the audit.
   ============================================================ */

/* FAQ accordion tap targets must hit the 44-px mobile minimum. */
.ds-op-faq-question {
  min-height: 44px;
}

/* ============================================================
   Page-level fade-in + toast / flash-message animations.
   Defined last so they can reference the motion tokens without
   needing overrides.
   ============================================================ */

@keyframes ls-page-fade-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* App-shell pages fade in when they load — subtle 300 ms entrance
   so every navigation within the app feels intentional. Marketing
   pages get no page fade: their entrance motion is the .ds-reveal
   scroll reveal below (custom.js, every page) plus, on the home page
   only, the GSAP reveals home.js runs on .ds-reveal-gsap.
   fill-mode is `backwards` (not `both`): a forwards-filled transform
   keeps computing as a transform after the animation ends, which turns
   the container into the containing block for every position:fixed
   descendant (mobile filter sheet, modals) and pins them to the page
   instead of the viewport. */
.app-shell .app-container {
  animation: ls-page-fade-in 340ms var(--ds-ease-standard) backwards;
}

/* ============================================================
   Global scroll-reveal + stagger system
   Driven by custom.js IntersectionObserver. Any element with class
   .ds-reveal or attribute [data-reveal] starts hidden and animates
   into place when it scrolls into view. Stagger delays are injected
   inline by the JS observer for children of a .ds-stagger-parent.

   .ds-reveal-gsap / .ds-stagger-child-gsap are deliberately NOT included here —
   those are managed by the GSAP / ScrollTrigger pipeline in home.js
   on the one-pager and must not fight with IntersectionObserver.
   ============================================================ */
.ds-reveal,
[data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.75s var(--ds-ease-standard),
    transform 0.75s var(--ds-ease-standard);
  will-change: opacity, transform;
}

/* Variants — different entrance directions + scale effects. */

.ds-reveal.is-revealed,
[data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0) translateX(0) scale(1);
}

/* ============================================================
   Icon micro-interactions
   Icons next to CTAs or inline links nudge slightly when the
   parent is hovered. Nothing flashy — 2 px translate for arrows,
   subtle rotate for gear / chevron icons.
   ============================================================ */
a .bi-arrow-right,
button .bi-arrow-right {
  display: inline-block;
  transition: transform var(--ds-dur-fast) var(--ds-ease-standard);
}

a:hover > .bi-arrow-right,
button:hover > .bi-arrow-right {
  transform: translateX(3px);
}

a:hover > .bi-arrow-left {
  transform: translateX(-3px);
}

.bi-arrow-left {
  display: inline-block;
  transition: transform var(--ds-dur-fast) var(--ds-ease-standard);
}

/* ============================================================
   Inline link underline slide
   Content-area links (legal, blog, FAQ answers) get a subtle
   underline-slide on hover for a classy feel.
   ============================================================ */
.blog-article a,
.ds-op-faq-answer a {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition:
    background-size 0.35s var(--ds-ease-standard),
    color var(--ds-dur-fast) var(--ds-ease-standard);
  text-decoration: none;
}

.blog-article a:hover,
.ds-op-faq-answer a:hover {
  background-size: 100% 1px;
  color: var(--ds-blue);
}

/* ========================================================================
   LANDING PAGE (lp-*) — Full-bleed landing page on home.html
   Dashboard language (palette, typography, orbs, gradients) preserved.
   ======================================================================== */

.ds-shell {
  background: var(--ds-white);
  /* `overflow-x: clip` (set globally on html/body above) is preferred over
       `hidden` because hidden auto-promotes overflow-y to auto, which makes
       the body itself the scroll container and breaks `position: sticky` on
       the .ds-site-header. The global clip rule already handles horizontal
       overflow for decorative orbs, so this scope only sets the surface. */
}

.ds-section--dark h2,
.ds-section--dark h3,
.ds-section--dark p {
  color: inherit;
}

.ds-section-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.ds-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.35;
}
.ds-orb-blue {
  background: radial-gradient(
    circle,
    rgba(var(--ds-blue-rgb), 0.6),
    transparent 70%
  );
}
.ds-orb-purple {
  background: radial-gradient(
    circle,
    rgba(var(--ds-purple-rgb), 0.55),
    transparent 70%
  );
}
.ds-orb-red {
  background: radial-gradient(
    circle,
    rgba(var(--ds-red-rgb), 0.45),
    transparent 70%
  );
}

.ds-wrap {
  position: relative;
  z-index: 1;
  /* Explicit width: inside a flex parent (e.g. .ds-hero--dramatic) the auto
       inline margins suppress cross-axis stretching, so without it the wrap
       sizes to fit-content — a nowrap child (hero ticker marquee) then
       inflates it past the viewport and the hero clips below 1280px. */
  width: 100%;
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

/* Constrained-width variant for staff-only metrics pages (960 px reading
   column, narrower than the default 1280 px full-width wrap). */
.ds-wrap--metrics {
  max-width: 960px;
}

/* Legacy Phase-1 .ds-hero / .ds-hero-grid / .ds-eyebrow rules removed —
   superseded by Phase-2 .ds-hero / .ds-hero__grid / .ds-eyebrow component
   system further below. The pre-migration flex + min-height constraints
   broke Mobile wrapping. */

.ds-eyebrow-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ds-success-bright);
  box-shadow: 0 0 0 0 rgba(var(--ds-success-bright-rgb), 0.6);
  animation: ds-pulse 2s ease-in-out infinite;
}
@keyframes ds-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(var(--ds-success-bright-rgb), 0.6);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(var(--ds-success-bright-rgb), 0);
  }
}
/* Legacy Phase-1 .ds-hero-title / -lead / -actions rules removed.
   Phase-2 uses BEM double-underscore: .ds-hero__title, .ds-hero__lead, .ds-hero__actions. */
.ds-hero-meta {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink);
  opacity: 0.75;
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.ds-hero-meta i {
  color: var(--ds-blue);
  margin-right: 0.3rem;
}

.ds-hero-mockup {
  position: relative;
  background: var(--ds-white);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-lg);
  box-shadow:
    0 32px 80px rgba(var(--ds-black-rgb), 0.35),
    0 16px 32px rgba(var(--ds-blue-rgb), 0.18);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.ds-hero-mockup-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.ds-mockup-chips {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.ds-mockup-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-blue-rgb), 0.08);
  color: var(--ds-blue);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-semi);
}
.ds-mockup-chip i {
  font-size: var(--ds-text-caption);
  opacity: 0.7;
}
.ds-mockup-count {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.8rem;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-success-bright-rgb), 0.1);
  color: var(--ds-success);
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-body-sm);
}
.ds-mockup-count::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ds-success-bright);
  animation: ds-pulse 2s ease-in-out infinite;
}
.ds-mockup-leads {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.ds-mockup-lead {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.9rem;
  align-items: center;
  padding: 0.85rem 1rem;
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-sm);
  background: var(--ds-white);
  transition:
    transform 0.35s var(--ds-ease-out),
    background 0.3s ease,
    border-color 0.3s ease;
}
.ds-mockup-lead--unlocked {
  border-color: rgba(var(--ds-success-bright-rgb), 0.3);
}
.ds-mockup-lead-score {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: var(--ds-fw-black);
  font-size: var(--ds-text-caption);
  color: var(--ds-white);
  background: conic-gradient(
    var(--ds-blue) 0% 80%,
    rgba(var(--ds-blue-rgb), 0.15) 80% 100%
  );
}
.ds-mockup-lead-score span {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--ds-white);
  color: var(--ds-blue);
  display: grid;
  place-items: center;
}
.ds-mockup-lead-body {
  min-width: 0;
}
.ds-mockup-lead-name {
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-body);
  color: var(--ds-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ds-mockup-lead-meta {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink);
  opacity: 0.7;
}
.ds-mockup-lead-contact {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink);
  margin-top: 0.2rem;
}
/* Blur is uniformly 4px across the product (mirrors .ds-lead-contact). */
.ds-mockup-lead--blurred .ds-mockup-lead-contact {
  filter: blur(4px);
  user-select: none;
}
.ds-mockup-lead-badge {
  font-size: var(--ds-text-caption);
  padding: 0.2rem 0.55rem;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-success-bright-rgb), 0.12);
  color: var(--ds-success);
  font-weight: var(--ds-fw-bold);
}
.ds-mockup-lead-lock {
  color: var(--ds-blue);
  opacity: 0.6;
}

@media (max-width: 991px) {
  .ds-hero {
    min-height: auto;
  }
  .ds-hero-mockup {
    margin-top: 1rem;
  }
}

/* ----- Trust-Bar ----- */
.ds-trust {
  padding-block: 2.5rem;
}
.ds-trust-row {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}
.ds-trust-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 1.1rem;
  border-radius: var(--ds-radius-full);
  background: var(--ds-white);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  color: var(--ds-ink);
  font-weight: var(--ds-fw-semi);
  font-size: var(--ds-text-body-sm);
  box-shadow: 0 2px 6px rgba(var(--ds-blue-rgb), 0.04);
}
.ds-trust-pill i {
  color: var(--ds-blue);
}
@media (max-width: 767px) {
  .ds-trust-row {
    overflow-x: auto;
    flex-wrap: nowrap;
    justify-content: flex-start;
    padding-inline: 0.5rem;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    mask-image: linear-gradient(
      to right,
      var(--ds-black) 0,
      var(--ds-black) 85%,
      transparent 100%
    );
    -webkit-mask-image: linear-gradient(
      to right,
      var(--ds-black) 0,
      var(--ds-black) 85%,
      transparent 100%
    );
  }
  .ds-trust-row::-webkit-scrollbar {
    display: none;
  }
  .ds-trust-pill {
    flex: 0 0 auto;
    scroll-snap-align: start;
  }
}

/* ----- Section headings ----- */
.ds-section-head {
  max-width: 720px;
  margin: 0 auto 3rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.ds-section-head .ds-eyebrow {
  margin-bottom: 1rem;
}
.ds-section-head h2 {
  font-size: clamp(2rem, 3.5vw, 2.75rem);
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 0.75rem;
  position: relative;
  display: inline-block;
}
.ds-section-head p {
  font-size: 1.05rem;
  color: var(--ds-ink);
  opacity: 0.8;
  margin: 0;
}
.ds-section--dark .ds-section-head h2 {
  color: var(--ds-white);
}
.ds-section--dark .ds-section-head p {
  color: rgba(var(--ds-white-rgb), 0.8);
}

/* ----- Problem ----- */
.ds-problem-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

/* .ds-problem-icon base styling — grid-area + position are layout-specific.
   Colors/hover are unified via the shared icon-tile block further down. */
.ds-problem-icon {
  grid-area: icon;
  position: relative;
  z-index: 1;
  width: 48px;
  height: 48px;
  border-radius: var(--ds-radius-md);
  font-size: 1.35rem;
}
.ds-problem-body {
  grid-area: body;
  min-width: 0;
  position: relative;
  z-index: 1;
}

.ds-problem-chip {
  grid-area: chip;
  align-self: start;
  margin-top: 0.25rem;
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.7rem;
  border-radius: var(--ds-radius-full);
  font-size: 0.72rem;
  font-weight: var(--ds-fw-bold);
  letter-spacing: 0.02em;
  color: var(--ds-danger);
  background: rgba(var(--ds-red-rgb), 0.08);
  border: 1px solid rgba(var(--ds-red-rgb), 0.15);
  white-space: nowrap;
  position: relative;
  z-index: 1;
  transition:
    background 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
}
@media (max-width: 575px) {
  .ds-problem-chip {
    justify-self: end;
    margin-top: 0;
  }
}
@media (max-width: 767px) {
  .ds-problem-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Solution Split ----- */
.ds-solution-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.ds-solution-copy h2 {
  font-size: clamp(2rem, 3.5vw, 2.75rem);
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 1rem 0 1rem;
}
.ds-solution-copy p {
  font-size: 1.05rem;
  color: var(--ds-ink);
  line-height: var(--ds-lh-prose);
  margin: 0 0 1.5rem;
}
.ds-solution-bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.ds-solution-bullets li {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: var(--ds-text-body);
  color: var(--ds-ink);
  line-height: 1.55;
}
.ds-solution-bullets i {
  color: var(--ds-blue);
  font-size: var(--ds-text-lg);
  margin-top: 0.15rem;
  flex-shrink: 0;
}
/* Keep each bold key-phrase on a single line. In the flex row the label would
   otherwise shrink and wrap to two lines ("Trefferzahl in / Echtzeit"), which
   read as broken. nowrap only guards the label itself, so on very narrow
   screens it still drops to its own line rather than overflowing. */
.ds-solution-bullets li strong {
  white-space: nowrap;
}

.ds-solution-mockup {
  position: relative;
  isolation: isolate;
  background: var(--ds-white);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-lg);
  box-shadow: 0 24px 60px rgba(var(--ds-blue-rgb), 0.14);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.ds-solution-mockup-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--ds-border-subtle);
  font-size: var(--ds-text-body-sm);
}
.ds-solution-mockup-row:last-child {
  border-bottom: none;
}
.ds-solution-mockup-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ds-ink);
  font-weight: var(--ds-fw-semi);
}
.ds-solution-mockup-label i {
  color: var(--ds-blue);
}
.ds-solution-mockup-check {
  width: 20px;
  height: 20px;
  border-radius: var(--ds-radius-xs);
  border: 2px solid var(--ds-blue);
  background: var(--ds-blue);
  color: var(--ds-white);
  display: grid;
  place-items: center;
  font-size: var(--ds-text-eyebrow);
  flex-shrink: 0;
}

.ds-solution-mockup-value {
  color: var(--ds-ink);
  opacity: 0.75;
}
@media (max-width: 991px) {
  .ds-solution-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Feature Grid ----- */
.ds-feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem 2.25rem;
}
@media (max-width: 991px) {
  .ds-feature-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 575px) {
  .ds-feature-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Process ----- */
.ds-process {
  position: relative;
}
.ds-process-track {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
  padding-top: 2.5rem;
}
.ds-process-track::before {
  content: "";
  position: absolute;
  top: 3.75rem;
  left: 10%;
  right: 10%;
  height: 2px;
  background: rgba(var(--ds-blue-rgb), 0.15);
  z-index: 0;
}
.ds-process-track::after {
  content: "";
  position: absolute;
  top: 3.75rem;
  left: 10%;
  height: 2px;
  background: linear-gradient(90deg, var(--ds-blue), var(--ds-purple));
  z-index: 1;
  width: var(--ds-process-fill, 0%);
  max-width: 80%;
  transition: width 0.3s ease;
}
.ds-process-step {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 0 0.5rem;
}
.ds-process-marker {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--ds-white);
  border: 2px solid rgba(var(--ds-blue-rgb), 0.2);
  color: var(--ds-blue);
  display: grid;
  place-items: center;
  font-weight: var(--ds-fw-black);
  font-size: var(--ds-text-body);
  transition:
    transform 0.3s ease,
    background 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
}
.ds-process-step.is-active .ds-process-marker,
.ds-process-step:hover .ds-process-marker {
  background: var(--ds-blue);
  color: var(--ds-white);
  border-color: var(--ds-blue);
  transform: scale(1.08);
}
.ds-process-step .icon-tile {
  margin: 0.75rem 0 0.5rem;
  transition:
    transform 0.5s var(--ds-ease-out),
    box-shadow 0.5s ease;
}
.ds-process-step h3 {
  font-size: var(--ds-text-lg);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0 0 0.4rem;
}
.ds-process-step p {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink);
  line-height: 1.55;
  margin: 0;
  max-width: 260px;
}
@media (max-width: 767px) {
  .ds-process-track {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .ds-process-track::before,
  .ds-process-track::after {
    top: 0;
    bottom: 0;
    left: 1.25rem;
    right: auto;
    width: 2px;
    height: auto;
  }
  .ds-process-track::after {
    height: var(--ds-process-fill, 0%);
    width: 2px;
    max-height: 100%;
    background: linear-gradient(180deg, var(--ds-blue), var(--ds-purple));
  }
  .ds-process-step {
    /* Keep the column stack: icon, title and paragraph are direct flex
           children — a row direction would squeeze them into three side-by-
           side mini-columns next to the absolute timeline marker. */
    flex-direction: column;
    text-align: left;
    align-items: flex-start;
    padding-left: 3.5rem;
  }
  .ds-process-step .ds-process-marker {
    position: absolute;
    left: 0;
    top: 0;
  }
  .ds-process-step .icon-tile {
    margin: 0 0 0.5rem;
  }
  .ds-process-step p {
    /* The 260px desktop measure fights the narrow timeline column. */
    max-width: none;
  }
}

/* ----- Use-Cases ----- */
.ds-usecase-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem;
}

.ds-usecase-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.25rem;
}
.ds-usecase-avatar {
  width: 44px;
  height: 44px;
  border-radius: var(--ds-radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ds-gradient-icon-tile);
  color: var(--ds-white);
  font-size: var(--ds-text-lg);
  box-shadow: var(--ds-shadow-icon-tile);
  flex-shrink: 0;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.ds-usecase-tag {
  display: inline-block;
  padding: 0.35rem 0.8rem;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-blue-rgb), 0.08);
  color: var(--ds-blue);
  font-size: 0.72rem;
  font-weight: var(--ds-fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.ds-usecase-metric {
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
  padding: 0.85rem 1rem;
  border-radius: var(--ds-radius-md);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.05),
    rgba(var(--ds-purple-rgb), 0.04)
  );
  border: 1px solid var(--ds-border-subtle);
}
.ds-usecase-metric-value {
  font-size: clamp(1.75rem, 3.2vw, 2.4rem);
  font-weight: var(--ds-fw-black);
  line-height: 1;
  letter-spacing: var(--ds-tracking-tight);
  background: var(--ds-gradient-icon-tile);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ds-usecase-metric-unit {
  font-size: 0.55em;
  font-weight: var(--ds-fw-bold);
  margin-left: 0.1em;
  /* Break inheritance of gradient-text clipping from the parent metric-value
       so characters like "h" / "T€" stay visible in brand blue. */
  color: var(--ds-blue);
  -webkit-text-fill-color: var(--ds-blue);
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  opacity: 1;
}
.ds-usecase-metric-label {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink);
  line-height: 1.3;
  font-weight: var(--ds-fw-medium);
  opacity: 0.85;
}

.ds-usecase-bullets {
  list-style: none;
  padding: 1rem 0 0;
  margin: auto 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  border-top: 1px solid var(--ds-border-subtle);
}
.ds-usecase-bullets li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink);
  line-height: 1.45;
}
.ds-usecase-bullets i {
  color: var(--ds-success);
  margin-top: 0.15rem;
  flex-shrink: 0;
  font-size: var(--ds-text-body);
}
@media (max-width: 991px) {
  .ds-usecase-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Comparison (dark) — closing call to action below the table -----
   The table itself, its indicator colours and the <768px card collapse all
   live in the "=== Compare Table ===" section next to .ds-compare-table. */

.ds-compare-cta {
  text-align: center;
  margin-top: 2.5rem;
}
.ds-compare-cta p {
  color: rgba(var(--ds-white-rgb), 0.8);
  margin: 0 0 1rem;
}

/* ----- Industries ----- */
.ds-industry-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}
.ds-industry-chip {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.5rem 1.5rem;
  background: var(--ds-white);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  overflow: hidden;
  transition:
    transform 0.4s var(--ds-ease-out),
    box-shadow 0.4s ease,
    border-color 0.3s ease;
}

/* Gradient-Top-Bar signature — same pattern as .ds-card */
.ds-industry-chip::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--ds-gradient-brand);
  opacity: 0;
  transform: translateY(-100%);
  transition:
    opacity var(--ds-dur-base) var(--ds-ease-out),
    transform var(--ds-dur-base) var(--ds-ease-out);
  pointer-events: none;
  z-index: 2;
}
.ds-industry-chip:hover::before {
  opacity: 1;
  transform: translateY(0);
}
.ds-industry-chip__body {
  min-width: 0; /* allow flex children to wrap */
}
.ds-industry-chip h3 {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0 0 0.3rem;
  line-height: 1.25;
  text-transform: none;
  letter-spacing: 0;
}
.ds-industry-chip p {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  margin: 0;
  line-height: var(--ds-lh-base);
  word-break: break-word;
}
@media (max-width: 991px) {
  .ds-industry-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 575px) {
  .ds-industry-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Pricing ----- */
.ds-pricing-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
  align-items: stretch;
}

/* The parallel ds-pricing-* sub-element vocabulary (badge/icon/tier/name/
   price/credits/features/cta) was deleted when the home pricing section was
   consolidated onto the canonical ds-card--pricing markup shared with
   /app/billing/plans/. Only the shared grid below remains. */

@media (max-width: 991px) {
  .ds-pricing-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 575px) {
  .ds-pricing-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Top-ups ----- */
.ds-extras-block h3 {
  font-size: 1.25rem;
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  margin: 0 0 0.5rem;
}
.ds-extras-block p {
  font-size: var(--ds-text-body);
  color: var(--ds-ink);
  margin: 0 0 1.25rem;
  line-height: 1.55;
}
.ds-topup-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.5rem;
}
.ds-topup {
  padding: 0.9rem 0.5rem;
  background: var(--ds-white);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-sm);
  text-align: center;
  transition:
    border-color 0.2s ease,
    transform 0.2s ease;
}
.ds-topup:hover {
  border-color: var(--ds-blue);
  transform: translateY(-2px);
}

.ds-topup-label {
  font-size: var(--ds-text-eyebrow);
  color: var(--ds-blue);
  font-weight: var(--ds-fw-bold);
  text-transform: uppercase;
  margin: 0.25rem 0 0.4rem;
}

@media (max-width: 575px) {
  .ds-topup-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ----- FAQ ----- */
.ds-faq-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 2rem;
  align-items: start;
}
.ds-faq-grid .ds-op-faq-item {
  background: var(--ds-white);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm);
  padding: 0;
  overflow: hidden;
  transition: none;
  box-shadow: none;
}
.ds-faq-grid .ds-op-faq-item.is-open {
  /* Keep white background when expanded so the body text stays on a clean,
       high-contrast surface. */
  background: var(--ds-white);
  border-color: rgba(var(--ds-blue-rgb), 0.2);
  box-shadow: 0 4px 14px rgba(var(--ds-blue-rgb), 0.06);
}
/* Neutralise the generic .ds-op-faq-item rules (defined earlier in this
   file) that add animated background gradients or transitions — FAQ on the
   landing page must switch state instantly so the whole card fills solid
   grey at once. */
.ds-faq-grid .ds-op-faq-question {
  transition: none;
  background: transparent;
}
.ds-faq-grid .ds-op-faq-question:hover,
.ds-faq-grid .ds-op-faq-question:focus-visible {
  background: rgba(var(--ds-blue-rgb), 0.035);
}
@media (max-width: 767px) {
  .ds-faq-grid {
    grid-template-columns: 1fr;
  }
}

/* ----- Sticky CTA ----- */
.ds-sticky-cta.is-visible.is-near-footer {
  transform: translateY(120%);
  opacity: 0;
  pointer-events: none;
}
.ds-sticky-cta-text {
  flex: 1;
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.ds-sticky-cta-text i {
  color: var(--ds-amber);
}

.ds-sticky-cta-close {
  background: transparent;
  border: none;
  color: rgba(var(--ds-white-rgb), 0.6);
  font-size: 1.2rem;
  padding: 0.25rem 0.5rem;
  cursor: pointer;
  transition: color 0.2s ease;
}
.ds-sticky-cta-close:hover {
  color: var(--ds-white);
}

/* ================================================================
   LP Hero — Dark Aesthetic (Iteration 2)
   Layered atmosphere, glassmorphic mockup, mini-stats, ticker, scroll cue.
   Overrides .ds-section--atmo background on the dramatic hero.
   ================================================================ */

.ds-hero-grid-pattern {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--ds-white-rgb), 0.045) 1px, transparent 1px),
    linear-gradient(
      90deg,
      rgba(var(--ds-white-rgb), 0.045) 1px,
      transparent 1px
    );
  background-size: 56px 56px;
  mask-image: radial-gradient(
    ellipse 70% 65% at 50% 40%,
    var(--ds-black) 0%,
    transparent 90%
  );
  -webkit-mask-image: radial-gradient(
    ellipse 70% 65% at 50% 40%,
    var(--ds-black) 0%,
    transparent 90%
  );
  opacity: 0.8;
}

.ds-hero-conic {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 140%;
  aspect-ratio: 1;
  background: conic-gradient(
    from 180deg at 50% 50%,
    rgba(var(--ds-blue-rgb), 0.22) 0deg,
    rgba(var(--ds-purple-rgb), 0.14) 110deg,
    rgba(34, 211, 238, 0.12) 220deg,
    rgba(var(--ds-red-rgb), 0.1) 300deg,
    rgba(var(--ds-blue-rgb), 0.22) 360deg
  );
  filter: blur(70px);
  opacity: 0.55;
  animation: ds-hero-spin 55s linear infinite;
  will-change: transform;
}
@keyframes ds-hero-spin {
  from {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}

.ds-orb-cyan {
  background: radial-gradient(circle, rgba(34, 211, 238, 0.6), transparent 65%);
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.45;
}
.ds-orb--glow {
  mix-blend-mode: screen;
  animation: ds-orb-drift 16s ease-in-out infinite alternate;
}
@keyframes ds-orb-drift {
  0% {
    transform: translate(0, 0) scale(1);
  }
  50% {
    transform: translate(3%, -2%) scale(1.04);
  }
  100% {
    transform: translate(-2%, 3%) scale(0.98);
  }
}

.ds-hero-spot {
  position: absolute;
  top: var(--ds-hero-my, 50%);
  left: var(--ds-hero-mx, 50%);
  width: 420px;
  height: 420px;
  transform: translate(-50%, -50%);
  background: radial-gradient(
    circle,
    rgba(var(--ds-blue-on-dark-rgb), 0.22),
    transparent 60%
  );
  filter: blur(30px);
  opacity: 0.9;
  transition:
    top 0.5s cubic-bezier(0.22, 1, 0.36, 1),
    left 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
  mix-blend-mode: screen;
}

.ds-hero-particles {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.ds-hero-particle {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(var(--ds-white-rgb), 0.9),
    rgba(var(--ds-white-rgb), 0) 70%
  );
  opacity: 0;
  animation: ds-particle-float 14s linear infinite;
  will-change: transform, opacity;
}
@keyframes ds-particle-float {
  0% {
    transform: translateY(110vh) scale(0.8);
    opacity: 0;
  }
  10% {
    opacity: 0.7;
  }
  85% {
    opacity: 0.4;
  }
  100% {
    transform: translateY(-20vh) scale(1.15);
    opacity: 0;
  }
}

.ds-hero-beam {
  position: absolute;
  top: -15%;
  width: 2px;
  height: 130%;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(var(--ds-blue-on-dark-rgb), 0.55),
    transparent
  );
  filter: blur(1px);
  opacity: 0;
  animation: ds-beam-slide 9s ease-in-out infinite;
}
.ds-hero-beam--1 {
  left: 14%;
  animation-delay: 0s;
  transform: rotate(6deg);
}
@keyframes ds-beam-slide {
  0%,
  100% {
    transform: translateY(-10%) rotate(6deg);
    opacity: 0;
  }
  50% {
    transform: translateY(10%) rotate(6deg);
    opacity: 0.55;
  }
}
.ds-hero-beam--2 {
  right: 20%;
  animation-delay: 4.5s;
  transform: rotate(-8deg);
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(182, 157, 255, 0.55),
    transparent
  );
  animation-name: ds-beam-slide-alt;
}
@keyframes ds-beam-slide-alt {
  0%,
  100% {
    transform: translateY(10%) rotate(-8deg);
    opacity: 0;
  }
  50% {
    transform: translateY(-10%) rotate(-8deg);
    opacity: 0.55;
  }
}

/* ---- Text on dark ---- */

.ds-hero--dramatic .ds-hero-meta {
  color: var(--ds-white);
  opacity: 1;
  gap: 1.5rem;
  padding-top: 0.25rem;
}
.ds-hero--dramatic .ds-hero-meta i {
  color: var(--ds-white);
}

@keyframes ds-gradient-shimmer {
  0%,
  100% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
}

.ds-eyebrow-clock {
  font-variant-numeric: tabular-nums;
  font-weight: var(--ds-fw-medium);
  /* Inherit-on-light: clock reads dark-on-light in the standard frame.
       Dark-hero variant below overrides back to white-on-dark. */
  color: var(--ds-ink-soft);
  letter-spacing: 0.02em;
  text-transform: none;
  font-size: var(--ds-text-caption);
}

.ds-eyebrow--on-dark .ds-eyebrow-clock {
  color: rgba(var(--ds-white-rgb), 0.82);
}

.ds-eyebrow--on-dark .ds-eyebrow-sep {
  background: rgba(var(--ds-white-rgb), 0.18);
}

.ds-eyebrow-sep {
  width: 1px;
  height: 12px;
  background: rgba(var(--ds-blue-rgb), 0.18);
  display: inline-block;
  margin: 0 0.1rem;
}

.ds-button.ds-button--secondary.ds-button--secondary--on-dark {
  background: rgba(var(--ds-white-rgb), 0.06);
  color: var(--ds-white);
  border: 1px solid rgba(var(--ds-white-rgb), 0.18);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 8px 20px rgba(var(--ds-black-rgb), 0.25);
}
.ds-button.ds-button--secondary.ds-button--secondary--on-dark:hover,
.ds-button.ds-button--secondary.ds-button--secondary--on-dark:focus-visible {
  background: rgba(var(--ds-white-rgb), 0.12);
  border-color: rgba(var(--ds-white-rgb), 0.4);
  color: var(--ds-white);
  box-shadow: 0 14px 32px rgba(var(--ds-black-rgb), 0.4);
}
/* The elevation shadow above would otherwise replace the focus ring, because
   this selector outranks .ds-button:focus-visible and .ds-button clears the
   outline. Keep the elevation AND append the ring: on a translucent white
   fill over a dark band, the 6 % alpha shift of the hover state is not a
   perceivable focus indicator (WCAG 2.4.7 / 1.4.11). */
.ds-button.ds-button--secondary.ds-button--secondary--on-dark:focus-visible {
  box-shadow:
    0 14px 32px rgba(var(--ds-black-rgb), 0.4),
    0 0 0 3px var(--ds-ink-on-dark-accent);
}

/* ---- Mini-stat strip ---- */
/* Two columns, matching the two figures the hero can actually back with a
   measurement (pool size and filter count). A fixed third column left a
   ~200px hole in the panel once the unbacked response-time figure was
   removed. */
.ds-hero-minstats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin: 2.5rem 0 0;
  padding: 1.1rem 1.5rem;
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  background: linear-gradient(
    180deg,
    rgba(var(--ds-blue-rgb), 0.04),
    rgba(var(--ds-blue-rgb), 0.01)
  );
  border-radius: var(--ds-radius-md);
  box-shadow:
    0 8px 24px rgba(var(--ds-blue-rgb), 0.08),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.8);
  max-width: 560px;
}
.ds-hero-minstats div {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-inline: 1rem;
  border-right: 1px solid rgba(var(--ds-blue-rgb), 0.1);
}
.ds-hero-minstats div:first-child {
  padding-left: 0;
}
.ds-hero-minstats div:last-child {
  padding-right: 0;
  border-right: none;
}
.ds-hero-minstats dt {
  font-size: var(--ds-text-eyebrow);
  color: var(--ds-ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: var(--ds-fw-semi);
  margin: 0;
}
.ds-hero-minstats dd {
  margin: 0;
  font-size: 1.65rem;
  font-weight: var(--ds-fw-black);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: baseline;
  /* Gradient-text with fallback to solid blue for browsers without clip */
  color: var(--ds-blue);
  background: var(--ds-gradient-icon-tile);
  -webkit-background-clip: text;
  background-clip: text;
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .ds-hero-minstats dd {
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

/* Dark-hero variant of the landing-page hero (.ds-hero--dramatic on home.html) */
.ds-hero--dramatic .ds-hero-minstats {
  border-color: rgba(var(--ds-white-rgb), 0.08);
  background: linear-gradient(
    180deg,
    rgba(var(--ds-white-rgb), 0.04),
    rgba(var(--ds-white-rgb), 0.01)
  );
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow:
    0 16px 40px rgba(var(--ds-black-rgb), 0.25),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.06);
}
.ds-hero--dramatic .ds-hero-minstats div {
  border-right-color: rgba(var(--ds-white-rgb), 0.07);
}
.ds-hero--dramatic .ds-hero-minstats dt {
  color: rgba(var(--ds-white-rgb), 0.78);
}
.ds-hero--dramatic .ds-hero-minstats dd {
  background: linear-gradient(120deg, var(--ds-white) 0%, #b9ccff 100%);
  color: var(--ds-white);
  -webkit-background-clip: text;
  background-clip: text;
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .ds-hero--dramatic .ds-hero-minstats dd {
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}
/* The unit (+, s) next to the gradient-clipped number. Breaks gradient-text
   inheritance so characters stay visible. */
.ds-hero--dramatic .ds-hero-minstats-unit {
  color: rgba(var(--ds-white-rgb), 0.85);
  -webkit-text-fill-color: rgba(var(--ds-white-rgb), 0.85);
}
.ds-hero-minstats-unit {
  color: var(--ds-blue);
  -webkit-text-fill-color: var(--ds-blue);
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-bold);
  margin-left: 0.15rem;
}

/* The mockup panel on the dark-dramatic hero reads as a bright Dashboard
   card floating on the dark backdrop. Chips, count pill, lead rows keep
   their light-theme palette (blue-tinted + green-tinted + dark ink) —
   DO NOT override them to white-glass on the dramatic hero. */

/* Lead row hover — kept subtle across both light mockup and dark-variant */
.ds-mockup-lead:hover {
  transform: translateX(4px);
}

/* ---- Floating micro cards around mockup ---- */
.ds-hero-mockup-float {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.55rem 0.95rem;
  border-radius: var(--ds-radius-full);
  background: rgba(18, 22, 50, 0.92);
  border: 1px solid rgba(var(--ds-white-rgb), 0.12);
  color: var(--ds-white);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-semi);
  white-space: nowrap;
  box-shadow:
    0 16px 40px rgba(var(--ds-black-rgb), 0.5),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.08);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  z-index: 2;
  animation: ds-float-bob 5.5s ease-in-out infinite;
}
.ds-hero-mockup-float i {
  font-size: var(--ds-text-body);
}
.ds-hero-mockup-float--tl {
  top: -18px;
  left: -20px;
  animation-delay: 0s;
}
.ds-hero-mockup-float--tl i {
  color: var(--ds-success-on-dark);
}
.ds-hero-mockup-float--br {
  bottom: -18px;
  right: -20px;
  animation-delay: 2.5s;
}
.ds-hero-mockup-float--br i {
  color: var(--ds-amber);
}
@keyframes ds-float-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-7px);
  }
}

/* ---- Live ticker ---- */
.ds-hero-ticker {
  /* Halved from the original clamp(2.5rem, 5vw, 4rem) —
       stat strip and ticker are pulled closer together as a visual unit. */
  margin-top: clamp(1.25rem, 2.5vw, 2rem);
  /* Contain the nowrap marquee track: without these the ticker's
       min-content (~2700px) propagates up and inflates the hero wrap. */
  min-width: 0;
  max-width: 100%;
  padding: 0.85rem 1.25rem;
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  background: linear-gradient(
    90deg,
    rgba(var(--ds-blue-rgb), 0.04),
    rgba(var(--ds-blue-rgb), 0.02)
  );
  border-radius: var(--ds-radius-full);
  display: flex;
  align-items: center;
  gap: 1.25rem;
  overflow: hidden;
  position: relative;
  z-index: 1;
  box-shadow: 0 4px 14px rgba(var(--ds-blue-rgb), 0.05);
}
.ds-hero-ticker-label {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.72rem;
  font-weight: var(--ds-fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ds-ink-soft);
  padding-right: 1rem;
  border-right: 1px solid rgba(var(--ds-blue-rgb), 0.14);
  position: relative;
  z-index: 2;
}
.ds-hero-ticker-viewport {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    var(--ds-black) 8%,
    var(--ds-black) 92%,
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    var(--ds-black) 8%,
    var(--ds-black) 92%,
    transparent 100%
  );
}
.ds-ticker-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ds-success-bright);
  box-shadow: 0 0 0 4px rgba(var(--ds-success-bright-rgb), 0.25);
  animation: ds-pulse 2s ease-in-out infinite;
}
.ds-hero-ticker-track {
  display: inline-flex;
  gap: 2.25rem;
  white-space: nowrap;
  animation: ds-ticker-scroll 38s linear infinite;
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-medium);
  will-change: transform;
  padding-inline: 1rem;
}

/* Pause on hover: WCAG 2.2.2 wants a way to stop content that moves by
   itself for longer than five seconds. The OS-level reduced-motion setting
   already stops it outright (see the global media query at the end of this
   file); this covers the reader who simply wants to finish the line under
   the cursor. A dedicated pause control would be the complete answer and is
   noted as such — it is a new control, not a refinement of this one. */
.ds-hero-ticker:hover .ds-hero-ticker-track {
  animation-play-state: paused;
}
.ds-hero-ticker-track span {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.ds-hero-ticker-track i {
  color: var(--ds-blue);
  font-size: var(--ds-text-caption);
}

/* Dark-hero variant: white-on-dark glass ticker with the same deep drop-
   shadow as .ds-hero-minstats so both floating pills share one signature. */
.ds-hero--dramatic .ds-hero-ticker {
  border-color: rgba(var(--ds-white-rgb), 0.08);
  background: linear-gradient(
    90deg,
    rgba(var(--ds-white-rgb), 0.04),
    rgba(var(--ds-white-rgb), 0.02)
  );
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow:
    0 16px 40px rgba(var(--ds-black-rgb), 0.25),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.06);
}
.ds-hero--dramatic .ds-hero-ticker-label {
  color: rgba(var(--ds-white-rgb), 0.78);
  border-right-color: rgba(var(--ds-white-rgb), 0.12);
}
.ds-hero--dramatic .ds-hero-ticker-track {
  color: rgba(var(--ds-white-rgb), 0.6);
}
.ds-hero--dramatic .ds-hero-ticker-track i {
  color: rgba(var(--ds-blue-on-dark-rgb), 0.85);
}

@keyframes ds-ticker-scroll {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-50%);
  }
}

/* ---- Scroll cue ---- */
.ds-hero-scroll {
  position: absolute;
  bottom: 1.75rem;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.24em;
  font-weight: var(--ds-fw-bold);
  z-index: 3;
  transition:
    color 0.3s ease,
    transform 0.3s ease;
}
.ds-hero--dramatic .ds-hero-scroll {
  color: rgba(var(--ds-white-rgb), 0.72);
}
.ds-hero-scroll:hover,
.ds-hero-scroll:focus-visible {
  color: var(--ds-blue);
  transform: translateX(-50%) translateY(-2px);
}
.ds-hero--dramatic .ds-hero-scroll:hover,
.ds-hero--dramatic .ds-hero-scroll:focus-visible {
  color: var(--ds-white);
}
.ds-hero-scroll-line {
  width: 1px;
  height: 44px;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(var(--ds-white-rgb), 0.55)
  );
  position: relative;
  overflow: hidden;
}
.ds-hero-scroll-line::after {
  content: "";
  position: absolute;
  top: -60%;
  left: 0;
  width: 100%;
  height: 60%;
  background: linear-gradient(to bottom, transparent, var(--ds-white));
  animation: ds-scroll-dive 2.4s ease-in-out infinite;
}

/* Caption under the scroll line — quiet uppercase micro-label. */
.ds-hero-scroll-text {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  letter-spacing: 2px;
  text-transform: uppercase;
}
@keyframes ds-scroll-dive {
  0% {
    top: -60%;
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    top: 110%;
    opacity: 0;
  }
}

/* ---- Responsive ---- */
@media (max-width: 767px) {
  .ds-hero-minstats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0;
    padding: 0.9rem 0.9rem;
    margin-top: 2rem;
  }
  .ds-hero-minstats div {
    padding-inline: 0.5rem;
  }
  .ds-hero-minstats dd {
    font-size: var(--ds-text-lg);
  }
  .ds-hero-ticker {
    margin-top: 2rem;
    padding: 0.7rem 0.9rem;
    border-radius: var(--ds-radius-lg);
    flex-direction: column;
    align-items: flex-start;
    gap: 0.6rem;
  }
  .ds-hero-ticker-label {
    border-right: none;
    padding-right: 0;
  }
  .ds-hero-scroll {
    display: none;
  }
  .ds-hero-mockup-float {
    font-size: var(--ds-text-eyebrow);
    padding: 0.4rem 0.75rem;
  }
  .ds-hero-mockup-float--tl {
    top: -14px;
    left: 8px;
  }
  .ds-hero-mockup-float--br {
    bottom: -14px;
    right: 8px;
  }
}
/* ================================================================
   LP Fix — icon-tile base sizing across landing page components.
   The .icon-tile class was styled per-app (quick-action, ds-home-feature)
   but the landing page uses `.ds-process-step .icon-tile`,
   `.ds-industry-chip .icon-tile`,
   `.ds-extras-block .icon-tile`, which had NO width/height/display. In
   the dark-pattern feature section the 1px border rendered a wide
   bar — the "frame around icons" bug. This block gives each LP
   icon-tile a proper 44px flex-tile box with the brand gradient.
   ================================================================ */
/* ================================================================
   Unified icon-tile signature — same solid blue→purple gradient +
   white glyph as .ds-usecase-avatar. Applied to every icon container
   across the landing so the entire page reads with one icon voice.
   ================================================================ */
.ds-process-step .icon-tile,
.ds-industry-chip .icon-tile,
.ds-extras-block .icon-tile,
.ds-card--feature .ds-card__icon,
.ds-card--stat .ds-card__icon,
.ds-card .ds-card__icon,
.ds-link-card__icon,
.ds-problem-icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--ds-radius-sm);
  background: var(--ds-gradient-icon-tile);
  color: var(--ds-white);
  font-size: var(--ds-text-lg);
  line-height: 1;
  box-shadow: var(--ds-shadow-icon-tile);
  transition:
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.4s ease;
}
.ds-process-step:hover .icon-tile,
.ds-industry-chip:hover .icon-tile,
.ds-extras-block:hover .icon-tile,
.ds-card--feature:hover .ds-card__icon,
.ds-card:hover .ds-card__icon,
.ds-card:hover .ds-link-card__icon {
  transform: scale(1.08) rotate(-3deg);
  box-shadow: 0 14px 28px rgba(var(--ds-blue-rgb), 0.35);
}

/* Industry-chip gets the compact 36×36 variant but keeps the same gradient. */
.ds-industry-chip .icon-tile {
  width: 36px;
  height: 36px;
  font-size: var(--ds-text-body);
  border-radius: var(--ds-radius-sm);
  flex-shrink: 0;
  transition: transform var(--ds-dur-base) var(--ds-ease-spring);
}

/* ================================================================
   LP Iteration 3 — Continuity, animation, dark pockets
   Threads the hero's dark/gradient aesthetic through the rest of the
   page via: (a) a dark-pattern anchor section on the feature grid,
   (b) a dark pricing card for the featured plan, (c) subtle ambient
   orbs on every light/tint section, and (d) richer hover motion on
   problem tiles, industry chips, use-case cards, FAQ items.
   ================================================================ */

/* 1. Dark-pattern section variant (Feature Grid anchor) */
.ds-section--dark-pattern > .ds-wrap {
  position: relative;
  z-index: 1;
}
.ds-section--dark-pattern .ds-eyebrow {
  background: rgba(var(--ds-white-rgb), 0.07);
  color: rgba(var(--ds-white-rgb), 0.9);
  border: 1px solid rgba(var(--ds-white-rgb), 0.12);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.ds-section--dark-pattern .ds-section-head h2 {
  background: linear-gradient(120deg, var(--ds-white) 0%, #b9ccff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.ds-section--dark-pattern .ds-section-head p {
  color: rgba(var(--ds-white-rgb), 0.68);
}

/* 4. Industry chip shine sweep */
.ds-industry-chip::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 45%;
  height: 100%;
  background: linear-gradient(
    110deg,
    transparent 0%,
    rgba(var(--ds-blue-on-dark-rgb), 0.3) 50%,
    transparent 100%
  );
  transform: skewX(-18deg);
  transition: left 0.75s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.ds-industry-chip:hover::after {
  left: 120%;
}
.ds-industry-chip:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 28px rgba(var(--ds-blue-rgb), 0.12);
  border-color: rgba(var(--ds-blue-rgb), 0.3);
}
.ds-industry-chip:hover .icon-tile {
  /* Gentle tilt-and-pulse on hover — echoes the card-icon rotate. */
  transform: scale(1.1) rotate(-5deg);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.18),
    rgba(var(--ds-purple-rgb), 0.14)
  );
  color: var(--ds-blue);
}

/* 5. Featured pricing card — the legacy .ds-pricing-card dark variant was
   deleted together with the ds-pricing-* sub-element vocabulary (the markup
   uses ds-card--pricing/ds-card--featured everywhere). */

/* 8. Process active step intensifies */
.ds-process-step.is-active .icon-tile {
  box-shadow:
    0 12px 28px rgba(var(--ds-blue-rgb), 0.22),
    0 0 0 5px rgba(var(--ds-blue-rgb), 0.08);
  transform: scale(1.08);
}

/* 10. Ambient orb wash on flat light/tint sections for color continuity.
      Solution-Split, Use-Cases and the hero already carry their own orbs;
      these rules add a subtle color bleed to Trust, Problem, Process,
      Branchen, Pricing, Extras and FAQ so the gradient palette threads
      through the whole page. */
.ds-section--light,
.ds-section--tint {
  position: relative;
}
.ds-section--light::before,
.ds-section--tint::before {
  content: "";
  position: absolute;
  top: -15%;
  right: -10%;
  width: 520px;
  height: 520px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(var(--ds-purple-rgb), 0.07),
    transparent 70%
  );
  filter: blur(80px);
  pointer-events: none;
  z-index: 0;
}
.ds-section--light::after,
.ds-section--tint::after {
  content: "";
  position: absolute;
  bottom: -18%;
  left: -12%;
  width: 460px;
  height: 460px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(var(--ds-blue-rgb), 0.06),
    transparent 70%
  );
  filter: blur(90px);
  pointer-events: none;
  z-index: 0;
}
.ds-section--light > .ds-wrap,
.ds-section--tint > .ds-wrap {
  position: relative;
  z-index: 1;
}

/* 11. Solution mockup dark ambient halo behind the glass panel */
.ds-solution-mockup::before {
  content: "";
  position: absolute;
  inset: -30px -30px -30px 25%;
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.1),
    rgba(var(--ds-purple-rgb), 0.08)
  );
  border-radius: var(--ds-radius-lg);
  filter: blur(40px);
  z-index: -1;
  opacity: 0.9;
}

/* 12. Section-head gradient underline accent */
.ds-section-head h2::after {
  content: "";
  display: block;
  width: 56px;
  height: 3px;
  margin: 1.1rem auto 0;
  border-radius: var(--ds-radius-full);
  background: linear-gradient(
    90deg,
    var(--ds-blue),
    var(--ds-purple),
    var(--ds-red)
  );
  background-size: 200% 100%;
  animation: ds-gradient-shimmer 7s ease-in-out infinite;
}
.ds-section--dark .ds-section-head h2::after,
.ds-section--dark-pattern .ds-section-head h2::after {
  background: linear-gradient(90deg, #7cb0ff, #b69dff, #ff8e86);
  background-size: 200% 100%;
}

/* ============================================================================
 * DS COMPONENTS — Phase 2 Unification
 * The unified .ds-* namespace. The former legacy namespaces (.lp-*,
 * .app-prem-*, etc.) were consolidated into it during the Phase 2 migration.
 * ========================================================================== */

/* === Layout Shells === */

.ds-layout-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--ds-surface-tint);
  color: var(--ds-ink);
  font-family: var(--ds-font-display);
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-base);
}

.ds-layout-shell__body {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.ds-layout-shell--app .ds-layout-shell__body {
  padding: 0;
}

/* App-pages persistent backdrop — matches the dashboard hero treatment
   (blue→red orb clouds + a fine grid pattern) across the entire content
   area. Built from layered radial-gradients (for the orbs) plus a
   repeating dot-gradient (for the pattern). This is the single source of
   the orb+dot aesthetic on app pages — the heroes themselves stay bare. */
body.ds-layout-shell--app,
.ds-layout-shell--app {
  background-color: var(--ds-surface-tint);
  background-image:
        /* 4 soft orbs — one per page corner, blue/red/purple/blue. */
    radial-gradient(
      560px 560px at 4% 4%,
      rgba(var(--ds-blue-rgb), 0.22) 0%,
      transparent 60%
    ),
    radial-gradient(
      480px 480px at 96% 12%,
      rgba(var(--ds-red-rgb), 0.18) 0%,
      transparent 60%
    ),
    radial-gradient(
      520px 520px at 2% 72%,
      rgba(var(--ds-purple-rgb), 0.16) 0%,
      transparent 60%
    ),
    radial-gradient(
      480px 480px at 98% 96%,
      rgba(var(--ds-blue-rgb), 0.14) 0%,
      transparent 60%
    ),
    /* Fine dot pattern — mirrors the Dashboard hero SVG dots */
    radial-gradient(
        circle 1.5px at 2px 2px,
        rgba(var(--ds-blue-rgb), 0.14) 100%,
        transparent 100%
      );
  background-size:
    auto,
    auto,
    auto,
    auto,
    18px 18px;
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat;
  background-attachment: fixed;
}

/* Hero container itself is transparent so the body-level orbs + dots show
   through. Copy retains its natural dark ink. */
.ds-layout-shell--app .ds-hero,
.ds-layout-shell--app .ds-hero--standard {
  background: transparent;
}

/* ============================================================================
 * App-Sidebar — sticky left rail on app pages
 * Desktop (>= 1200px): 240px expanded; click-to-collapse to 64px (icons only)
 * Tablet (768-1199): 64px icon-rail by default; hover expands as overlay
 * Mobile (< 768): slide-over drawer via header burger; backdrop overlays main
 * ============================================================================ */

.ds-app-sidebar {
  position: fixed;
  top: var(--ds-site-header-h);
  left: 0;
  bottom: 0;
  width: var(--ds-sidebar-width);
  background: rgba(var(--ds-white-rgb), 0.82);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-right: 1px solid var(--ds-border-subtle);
  box-shadow: 2px 0 24px rgba(var(--ds-blue-rgb), 0.04);
  z-index: 90;
  overflow-x: hidden;
  overflow-y: auto;
  transition:
    width var(--ds-dur-base) var(--ds-ease-out),
    transform var(--ds-dur-base) var(--ds-ease-out);
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--ds-blue-rgb), 0.15) transparent;
}

.ds-app-sidebar::-webkit-scrollbar {
  width: 6px;
}
.ds-app-sidebar::-webkit-scrollbar-thumb {
  background: rgba(var(--ds-blue-rgb), 0.15);
  border-radius: var(--ds-radius-xs);
}

.ds-app-sidebar__inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding: var(--ds-space-4) var(--ds-space-3);
  gap: var(--ds-space-3);
}

/* Nav */
.ds-app-sidebar__nav {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-0-5);
  flex: 1 1 auto;
}

.ds-app-sidebar__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  padding: var(--ds-space-2-5) var(--ds-space-3);
  border-radius: var(--ds-radius-sm);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  text-decoration: none;
  transition:
    background var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out);
  white-space: nowrap;
}
.ds-app-sidebar__icon {
  flex-shrink: 0;
  width: 20px;
  text-align: center;
  font-size: var(--ds-text-body);
  color: var(--ds-ink-mute);
  transition: color var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-app-sidebar__label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-app-sidebar__item:hover {
  background: rgba(var(--ds-blue-rgb), 0.06);
  color: var(--ds-ink);
}
.ds-app-sidebar__item:hover .ds-app-sidebar__icon {
  color: var(--ds-blue);
}
.ds-app-sidebar__item:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

.ds-app-sidebar__item.is-active {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.1),
    rgba(var(--ds-purple-rgb), 0.08)
  );
  color: var(--ds-blue);
}
.ds-app-sidebar__item.is-active .ds-app-sidebar__icon {
  color: var(--ds-blue);
}
.ds-app-sidebar__item.is-active::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--ds-space-3));
  top: 8px;
  bottom: 8px;
  width: 3px;
  background: linear-gradient(180deg, var(--ds-blue) 0%, var(--ds-purple) 100%);
  border-radius: 0 3px 3px 0;
}

/* Secondary items differ by colour only — the size matches the base item. */
.ds-app-sidebar__item--secondary {
  color: var(--ds-ink-mute);
}

/* Collapsed-sidebar state: center icon-only items inside the 64px rail.
   The labels further down the cascade keep `opacity: 0` (used in transition)
   but stay in flow, so we must collapse them out of the flex layout here
   — otherwise their `flex: 1 1 auto` would swallow the free space and pin
   the icon to the left of the item, breaking `justify-content: center`. */
body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__item,
body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__collapse {
  justify-content: center;
  padding-inline: 0;
  gap: 0;
}

body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__label,
body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__collapse-label {
  flex: 0 0 0;
  width: 0;
  overflow: hidden;
}

.ds-app-sidebar__section-label {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
  padding: var(--ds-space-2-5) var(--ds-space-3) var(--ds-space-1-5);
}

/* Mobile-only marketing block — hidden on tablet/desktop */
.ds-app-sidebar__mobile-marketing {
  display: none;
}

/* Footer: wallet card + collapse toggle */
.ds-app-sidebar__footer {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  flex-shrink: 0;
  margin-top: auto;
  padding-top: var(--ds-space-3);
  border-top: 1px solid rgba(var(--ds-blue-rgb), 0.06);
}

.ds-app-sidebar__wallet {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  padding: var(--ds-space-2-5) var(--ds-space-3);
  border-radius: var(--ds-radius-sm);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.08),
    rgba(var(--ds-purple-rgb), 0.06)
  );
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  color: var(--ds-ink);
  text-decoration: none;
  transition:
    transform var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-app-sidebar__wallet:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(var(--ds-blue-rgb), 0.12);
}
.ds-app-sidebar__wallet:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}
.ds-app-sidebar__wallet .bi-coin {
  font-size: var(--ds-text-lg);
  color: var(--ds-blue);
  flex-shrink: 0;
}
.ds-app-sidebar__wallet-text {
  min-width: 0;
  flex: 1;
}
.ds-app-sidebar__wallet-value {
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  line-height: 1;
  letter-spacing: -0.01em;
}
.ds-app-sidebar__wallet-label {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-blue);
  margin-top: 3px;
  line-height: 1;
}
.ds-app-sidebar__wallet.is-low {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-warn-rgb), 0.1),
    rgba(var(--ds-warn-rgb), 0.05)
  );
  border-color: rgba(var(--ds-warn-rgb), 0.2);
}
.ds-app-sidebar__wallet.is-low .bi-coin,
.ds-app-sidebar__wallet.is-low .ds-app-sidebar__wallet-label {
  color: var(--ds-warn);
}
.ds-app-sidebar__wallet.is-critical {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-danger-rgb), 0.1),
    rgba(var(--ds-danger-rgb), 0.05)
  );
  border-color: rgba(var(--ds-danger-rgb), 0.22);
  animation: ds-sidebar-wallet-pulse 2s ease-in-out infinite;
}
.ds-app-sidebar__wallet.is-critical .bi-coin,
.ds-app-sidebar__wallet.is-critical .ds-app-sidebar__wallet-label {
  color: var(--ds-danger);
}
@keyframes ds-sidebar-wallet-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(var(--ds-danger-rgb), 0.2);
  }
  50% {
    box-shadow: 0 0 0 6px rgba(var(--ds-danger-rgb), 0);
  }
}

.ds-app-sidebar__logout-form {
  margin: 0;
  padding: 0;
}

.ds-app-sidebar__logout {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  width: 100%;
  padding: var(--ds-space-2-5) var(--ds-space-3);
  border: 0;
  background: transparent;
  border-radius: var(--ds-radius-sm);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  text-align: left;
  cursor: pointer;
  transition:
    background var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-app-sidebar__logout:hover {
  background: rgba(var(--ds-danger-rgb), 0.08);
  color: var(--ds-danger);
}
.ds-app-sidebar__logout:hover .ds-app-sidebar__icon {
  color: var(--ds-danger);
}
.ds-app-sidebar__logout:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

.ds-app-sidebar__collapse {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2-5);
  padding: var(--ds-space-2) var(--ds-space-3);
  border: 0;
  background: transparent;
  border-radius: var(--ds-radius-sm);
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-semi);
  cursor: pointer;
  transition:
    background var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-app-sidebar__collapse:hover {
  background: rgba(var(--ds-blue-rgb), 0.05);
  color: var(--ds-ink);
}
.ds-app-sidebar__collapse:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}
.ds-app-sidebar__collapse .bi {
  font-size: var(--ds-text-body);
  transition: transform var(--ds-dur-base) var(--ds-ease-out);
}
body.ds-sidebar-collapsed .ds-app-sidebar__collapse .bi {
  transform: rotate(180deg);
}

/* Main-content offset (desktop default). Only the left side clears the
   fixed sidebar; the right side keeps a small gutter instead of mirroring
   the sidebar width. The former symmetric "phantom space" centered the
   content but squeezed it so far that the lead tables clipped their score
   and action columns on every common desktop width — content-first wins,
   and the minor horizontal shift on sidebar toggle is the accepted
   trade-off. */
@media (min-width: 1200px) {
  body.ds-layout-shell--app .ds-layout-shell__body,
  body.ds-layout-shell--app .ds-site-footer {
    padding-inline: var(--ds-sidebar-width) var(--ds-space-6);
  }
  body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar {
    width: var(--ds-sidebar-width-collapsed);
  }
  body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__label,
  body.ds-layout-shell--app.ds-sidebar-collapsed .ds-app-sidebar__wallet-text,
  body.ds-layout-shell--app.ds-sidebar-collapsed
    .ds-app-sidebar__collapse-label,
  body.ds-layout-shell--app.ds-sidebar-collapsed
    .ds-app-sidebar__section-label {
    opacity: 0;
    pointer-events: none;
  }
}

/* Tablet: icon-rail by default, hover expands as overlay */
@media (min-width: 768px) and (max-width: 1199px) {
  body.ds-layout-shell--app .ds-app-sidebar {
    width: var(--ds-sidebar-width-collapsed);
  }
  body.ds-layout-shell--app .ds-layout-shell__body,
  body.ds-layout-shell--app .ds-site-footer {
    /* Left clears the 64px icon-rail; right keeps a small gutter so
           the constrained tablet width goes to content, not symmetry. */
    padding-inline: var(--ds-sidebar-width-collapsed) var(--ds-space-4);
  }
  body.ds-layout-shell--app .ds-app-sidebar__label,
  body.ds-layout-shell--app .ds-app-sidebar__wallet-text,
  body.ds-layout-shell--app .ds-app-sidebar__collapse-label,
  body.ds-layout-shell--app .ds-app-sidebar__section-label {
    opacity: 0;
    pointer-events: none;
  }
  body.ds-layout-shell--app .ds-app-sidebar:hover {
    width: var(--ds-sidebar-width);
    box-shadow: 8px 0 32px rgba(var(--ds-blue-rgb), 0.12);
  }
  body.ds-layout-shell--app .ds-app-sidebar:hover .ds-app-sidebar__label,
  body.ds-layout-shell--app .ds-app-sidebar:hover .ds-app-sidebar__wallet-text,
  body.ds-layout-shell--app
    .ds-app-sidebar:hover
    .ds-app-sidebar__collapse-label,
  body.ds-layout-shell--app
    .ds-app-sidebar:hover
    .ds-app-sidebar__section-label {
    opacity: 1;
    pointer-events: auto;
  }
  body.ds-layout-shell--app .ds-app-sidebar__collapse {
    display: none;
  }
}

/* Mobile: slide-over drawer */
@media (max-width: 767px) {
  body.ds-layout-shell--app .ds-app-sidebar {
    width: 280px;
    transform: translateX(-100%);
    box-shadow: 10px 0 40px rgba(var(--ds-black-rgb), 0.18);
    /* A translated drawer stays in the tab order: from the burger, keyboard
       focus walked into nine invisible nav links parked at x=-268 with no
       visible indicator anywhere on screen. `visibility: hidden` takes the
       closed drawer out of the tab order; it is delayed by the slide duration
       so the closing animation still plays, and reverts instantly on open. */
    visibility: hidden;
    transition:
      width var(--ds-dur-base) var(--ds-ease-out),
      transform var(--ds-dur-base) var(--ds-ease-out),
      visibility 0s linear var(--ds-dur-base);
  }
  body.ds-layout-shell--app.ds-sidebar-open .ds-app-sidebar {
    transform: translateX(0);
    visibility: visible;
    transition-delay: 0s;
  }
  body.ds-layout-shell--app .ds-layout-shell__body {
    padding-inline: 0;
  }
  /* Only neutralize the desktop sidebar offset — the minimal footer keeps
       its own gutter, otherwise its link row touches the viewport edge. */
  body.ds-layout-shell--app .ds-site-footer {
    padding-inline: var(--ds-space-6);
  }
  body.ds-layout-shell--app .ds-app-sidebar__collapse {
    display: none;
  }
  body.ds-layout-shell--app .ds-app-sidebar__mobile-marketing {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-0-5);
  }

  .ds-app-sidebar__backdrop {
    position: fixed;
    top: var(--ds-site-header-h);
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(10, 15, 26, 0.45);
    backdrop-filter: blur(2px);
    z-index: 89;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--ds-dur-base) var(--ds-ease-out);
  }
  body.ds-layout-shell--app.ds-sidebar-open .ds-app-sidebar__backdrop {
    opacity: 1;
    pointer-events: auto;
  }
}

.ds-layout-shell--auth .ds-layout-shell__body {
  align-items: center;
  justify-content: center;
  padding: var(--ds-space-8) var(--ds-space-4);
  min-height: calc(100vh - 120px);
}

.ds-layout-shell--auth .ds-auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-lg);
  box-shadow: var(--ds-shadow-md);
  padding: var(--ds-space-8) var(--ds-space-6);
}

@media (min-width: 576px) {
  .ds-layout-shell--auth .ds-auth-card {
    padding: var(--ds-space-10) var(--ds-space-8);
  }
}

.ds-layout-shell--auth .ds-auth-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ds-space-6);
  width: 100%;
  max-width: 420px;
  align-items: start;
}

.ds-layout-shell--auth .ds-auth-layout > .ds-auth-card {
  max-width: none;
}

.ds-layout-shell--auth .ds-auth-aside {
  display: none;
}

@media (min-width: 992px) {
  .ds-layout-shell--auth .ds-auth-layout {
    grid-template-columns: minmax(0, 420px) minmax(0, 360px);
    max-width: 820px;
    gap: var(--ds-space-8);
  }
  .ds-layout-shell--auth .ds-auth-aside {
    display: flex;
  }
}

.ds-layout-shell--marketing .ds-layout-shell__body {
  padding: 0;
}

/* === Eyebrow === */

.ds-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ds-blue);
  margin: 0;
  /* Glass-framed pill — same signature used across dramatic hero and all sections. */
  background: rgba(var(--ds-blue-rgb), 0.07);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.14);
  padding: 0.45rem 0.95rem;
  border-radius: var(--ds-radius-full);
  box-shadow: var(--ds-shadow-pill);
}

.ds-eyebrow::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-blue);
}

.ds-eyebrow--on-dark {
  background: rgba(var(--ds-white-rgb), 0.07);
  color: var(--ds-lavender);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border: 1px solid rgba(var(--ds-white-rgb), 0.14);
  padding: 0.5rem 1.05rem;
  box-shadow: var(--ds-shadow-pill-on-dark);
}

.ds-eyebrow--on-dark::before {
  background: var(--ds-lavender);
}

/* When an eyebrow already carries its own leading marker — a live pulsing
   dot (.ds-eyebrow-dot on marketing, .ds-app-eyebrow-dot on the app shell)
   or a leading icon — the static ::before dot would render a second,
   redundant dot. Suppress it so every eyebrow shows exactly one marker;
   plain text eyebrows keep the ::before dot as their marker. */
.ds-eyebrow:has(.ds-eyebrow-dot)::before,
.ds-eyebrow:has(.ds-app-eyebrow-dot)::before,
.ds-eyebrow:has(> i.bi)::before {
  display: none;
}

/* === Gradient Text === */

.ds-gradient-text {
  /* Solid fallback color first — browsers without background-clip: text
       support will see this color instead of invisible transparent text. */
  color: var(--ds-blue);
  background: var(--ds-gradient-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  display: inline-block;
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .ds-gradient-text {
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

.ds-gradient-text--on-dark {
  color: var(--ds-lavender);
  background: var(--ds-gradient-brand-on-dark);
  -webkit-background-clip: text;
  background-clip: text;
}

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .ds-gradient-text--on-dark {
    -webkit-text-fill-color: transparent;
  }
}

.ds-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  padding: 4px 9px;
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-semi);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: var(--ds-radius-full);
  line-height: 1.45;
  white-space: nowrap;
}

/* Solid badge backgrounds (not semi-transparent) for predictable WCAG AA
   contrast regardless of parent surface. At 11px small text + 600 weight, text
   must have ≥4.5:1 ratio on its own rendered bg. */
.ds-badge--neutral {
  background: var(--ds-neutral-tint-bg);
  color: var(--ds-neutral-tint-text);
}
.ds-badge--success {
  background: var(--ds-success-tint-bg);
  color: var(--ds-success-tint-text);
}
.ds-badge--warn {
  background: var(--ds-warn-tint-bg);
  color: var(--ds-warn-tint-text);
}
.ds-badge--danger {
  background: var(--ds-danger-tint-bg);
  color: var(--ds-danger-tint-text);
}
.ds-badge--info {
  background: var(--ds-info-tint-bg);
  color: var(--ds-info-tint-text);
}
.ds-badge--gradient {
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
}

/* Step counter — fixed round 24px square for numbered onboarding steps;
   the inline flow of the surrounding heading provides the gap. */
.ds-badge--step {
  width: 24px;
  height: 24px;
  padding: 0;
  justify-content: center;
  border-radius: var(--ds-radius-full);
}

/* === Alerts (info / success / warn / danger) ===
   Inline contextual banners for dashboards, auth-flow and form responses.
   Replaces Bootstrap .alert .alert-* — uses ds-tokens, radius-md, and the
   status-tint backgrounds from :root for consistent visual language. */

.ds-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-3);
  padding: var(--ds-space-3) var(--ds-space-4);
  border-radius: var(--ds-radius-md);
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-base);
  border: 1px solid transparent;
  color: var(--ds-ink);
}

.ds-alert > i.bi,
.ds-alert > i[class*="bi-"] {
  flex-shrink: 0;
  font-size: var(--ds-text-lg);
  line-height: 1.2;
  margin-top: 1px;
}

.ds-alert strong {
  color: inherit;
}

/* Bold first line of a multi-line alert body (reference §05). */
.ds-alert__title {
  font-weight: var(--ds-fw-bold);
  margin-bottom: var(--ds-space-0-5);
}

.ds-alert--info {
  background: var(--ds-info-tint);
  border-color: rgba(var(--ds-info-rgb), 0.18);
  color: var(--ds-info);
}
.ds-alert--success {
  background: var(--ds-success-tint);
  border-color: rgba(var(--ds-success-rgb), 0.18);
  color: var(--ds-success);
}
.ds-alert--warn {
  background: var(--ds-warn-tint);
  border-color: rgba(var(--ds-warn-rgb), 0.18);
  /* --ds-warn measures 4.39:1 on the warn tint and misses the 4.5:1 AA floor
     for body text; --ds-warn-deep reaches 7.92:1. The sibling variants
     (info/success/danger) already clear AA on their own tints, so only this
     one changes. */
  color: var(--ds-warn-deep);
}
.ds-alert--danger {
  background: var(--ds-danger-tint);
  border-color: rgba(var(--ds-danger-rgb), 0.18);
  color: var(--ds-danger);
}

/* Alert body text inherits ink-body, only icon + title carry the status-color. */
.ds-alert--info .ds-alert__body,
.ds-alert--success .ds-alert__body,
.ds-alert--warn .ds-alert__body,
.ds-alert--danger .ds-alert__body {
  color: var(--ds-ink);
}

/* === Buttons === */

.ds-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ds-space-2);
  padding: 9px 18px;
  font-family: inherit;
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-bold);
  line-height: 1.2;
  letter-spacing: 0.01em;
  border: 0;
  border-radius: var(--ds-radius-sm);
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-base) var(--ds-ease-out),
    background var(--ds-dur-base) var(--ds-ease-out),
    color var(--ds-dur-base) var(--ds-ease-out);
  position: relative;
  overflow: hidden;
  white-space: nowrap;
  /* A button can never be wider than the column it sits in. Without this a
     long label plus nowrap simply pushes past the viewport, and the page-level
     overflow-x:clip hides the fact instead of scrolling to it. */
  max-width: 100%;
}

.ds-button:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* Filled buttons carry the ring colour as their own background, so they
   need the inset white band to keep the focus indicator distinguishable. */
.ds-button--primary:focus-visible {
  box-shadow: var(--ds-shadow-focus-on-brand);
}

.ds-button:disabled,
.ds-button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* Press state. Hover is a pointer-only signal — on a touch device nothing
   between tap and page response tells the user the tap registered, which is
   what makes people tap a second time on a slow connection. The button
   settles back down out of its hover lift and shrinks a hair; every variant
   inherits it, so there is one press language instead of none. */
.ds-button:not(:disabled):not([aria-disabled="true"]):active {
  transform: translateY(1px) scale(0.985);
}

/* Icons inside buttons pick up a subtle slide/rotate on hover for extra
   tactile feedback. Arrow-right variants slide, rockets tilt. */
.ds-button i,
.ds-button svg {
  transition: transform var(--ds-dur-base) var(--ds-ease-spring);
}
.ds-button:hover i.bi-arrow-right,
.ds-button:hover svg {
  transform: translateX(3px);
}
.ds-button:hover i.bi-rocket-takeoff {
  transform: translateY(-2px) rotate(-8deg);
}
.ds-button:hover i.bi-tags,
.ds-button:hover i.bi-coin,
.ds-button:hover i.bi-chat-dots {
  transform: scale(1.15);
}

.ds-button--primary {
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  box-shadow: var(--ds-shadow-sm);
  /* Text-shadow darkens behind white glyphs so contrast stays >= AA even
       over the red-stop of the brand gradient. */
  text-shadow: 0 1px 2px rgba(var(--ds-black-rgb), 0.25);
}

.ds-button--primary::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    135deg,
    transparent 20%,
    rgba(var(--ds-white-rgb), 0.25) 50%,
    transparent 80%
  );
  transform: translateX(-100%);
  transition: transform 0.5s var(--ds-ease-out);
  pointer-events: none;
}

.ds-button--primary:hover,
.ds-button--primary:focus-visible,
a.ds-button--primary:hover,
a.ds-button--primary:focus-visible {
  /* Hover solidifies to deep brand blue — high contrast with white text
       (var(--ds-white) on #053580 ≈ 9.6:1) so 'Kostenlos starten' stays crisp.
       The explicit color + a.<class>:hover selector defeats the global
       a:hover { color: var(--ds-blue-dark) } base rule that otherwise
       recolored the text to dark blue on blue. */
  background: var(--ds-blue-deep);
  color: var(--ds-white);
  transform: translateY(-1px);
  box-shadow: var(--ds-shadow-primary-hover);
}

.ds-button--primary:hover::after {
  transform: translateX(100%);
}

.ds-button--secondary {
  background: transparent;
  color: var(--ds-blue);
  border: 1px solid var(--ds-blue);
}

.ds-button--secondary:hover {
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  border-color: transparent;
  transform: translateY(-1px);
}

.ds-button--secondary:focus-visible {
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  border-color: transparent;
  transform: translateY(-1px);
  box-shadow: var(--ds-shadow-focus);
}

.ds-button--secondary--on-dark {
  color: var(--ds-white);
  border-color: rgba(var(--ds-white-rgb), 0.4);
}

.ds-button--secondary--on-dark:hover {
  background: rgba(var(--ds-white-rgb), 0.12);
  border-color: rgba(var(--ds-white-rgb), 0.6);
}

.ds-button--ghost {
  background: transparent;
  color: var(--ds-ink);
}

.ds-button--ghost:hover {
  background: var(--ds-surface-tint);
  color: var(--ds-blue);
}

.ds-button--danger {
  background: var(--ds-danger);
  color: var(--ds-white);
}

.ds-button--danger:hover {
  background: var(--ds-danger-bright);
  transform: translateY(-1px);
  box-shadow: var(--ds-shadow-danger-hover);
}

.ds-button--danger:focus-visible {
  background: var(--ds-danger-bright);
  transform: translateY(-1px);
  box-shadow: var(--ds-shadow-focus-on-danger);
}

.ds-button--sm {
  padding: var(--ds-space-1-5) var(--ds-space-3);
  font-size: var(--ds-text-caption);
  border-radius: var(--ds-radius-xs);
}

.ds-button--lg {
  padding: var(--ds-space-3) var(--ds-space-6);
  font-size: 15px;
  border-radius: var(--ds-radius-md);
}

.ds-button--block {
  display: flex;
  width: 100%;
}

/* On a phone a sentence-length label (the billing page's "Im Kundenportal
   kündigen oder Zahlungsmittel ändern" measures 433px) has no room to stay on
   one line. Allowing the wrap costs nothing for the short labels — they never
   reach their max-width — and is the only alternative to cutting the label off
   at the screen edge. The icon stays put: it is a flex item, so white-space
   does not move it. */
@media (max-width: 575px) {
  .ds-button {
    white-space: normal;
  }
}

/* Loading state — applied while a submit/POST is in flight. Pairs with an
   inline <span class="ds-spinner ds-spinner--sm"> before the label; pointer
   events are disabled so the styled state cannot fire a double submit. */
.ds-button.is-loading {
  pointer-events: none;
  opacity: 0.8;
}

.ds-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  padding: var(--ds-space-6) var(--ds-space-5);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-sm);
  transition:
    transform var(--ds-dur-base) var(--ds-ease-out),
    box-shadow var(--ds-dur-base) var(--ds-ease-out),
    border-color var(--ds-dur-base) var(--ds-ease-out);
  overflow: hidden;
  color: var(--ds-ink);
  text-decoration: none;
}

.ds-card::before {
  content: "";
  position: absolute;
  /* Sit flush at the card's padding-box top. The card's 1px border-top is
       hidden on hover (border-top-color: transparent) so the gradient reads
       as the whole top edge without a white hairline between bar and card. */
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--ds-gradient-brand);
  opacity: 0;
  transform: translateY(-100%);
  transition:
    opacity var(--ds-dur-base) var(--ds-ease-out),
    transform var(--ds-dur-base) var(--ds-ease-out);
  pointer-events: none;
  z-index: 2;
}

.ds-card:hover,
.ds-card:focus-within {
  /* Card hover identity — translateY + shadow + gradient top-bar (::before).
       Border-top goes transparent so the gradient bar reads as the card's
       single clean top edge. */
  transform: translateY(-4px);
  box-shadow: var(--ds-shadow-lg);
  border-top-color: transparent;
}

/* Diagonal shine sweep across cards on hover — matches the button shimmer. */
.ds-card::after {
  content: "";
  position: absolute;
  top: 0;
  left: -30%;
  width: 40%;
  height: 100%;
  background: linear-gradient(
    105deg,
    transparent 20%,
    rgba(var(--ds-white-rgb), 0.35) 50%,
    transparent 80%
  );
  transform: skewX(-16deg);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 0.9s var(--ds-ease-out),
    opacity 0.25s ease;
  z-index: 1;
}
.ds-card:hover::after,
.ds-card:focus-within::after {
  opacity: 0.9;
  transform: skewX(-16deg) translateX(420%);
}

/* Feature-card icon tile scales up slightly on hover for a tactile lift. */
.ds-card .ds-card__icon,
.ds-card .icon-tile {
  transition:
    transform var(--ds-dur-base) var(--ds-ease-spring),
    box-shadow var(--ds-dur-base) var(--ds-ease-out);
}
.ds-card:hover .ds-card__icon,
.ds-card:hover .icon-tile {
  transform: scale(1.08) rotate(-3deg);
  filter: drop-shadow(0 4px 10px rgba(var(--ds-blue-rgb), 0.25));
}

/* Feature cards on the dark-pattern section need a more visible shadow so the
   lift effect is perceivable on the dark backdrop. */
.ds-section--dark-pattern .ds-card:hover,
.ds-section--dark-pattern .ds-card:focus-within {
  box-shadow:
    0 8px 22px rgba(var(--ds-black-rgb), 0.28),
    0 24px 60px rgba(var(--ds-blue-rgb), 0.24);
}

.ds-card:hover::before,
.ds-card:focus-within::before {
  opacity: 1;
  transform: translateY(0);
}

.ds-card--compact {
  padding: var(--ds-space-4);
  gap: var(--ds-space-2);
}

.ds-card--featured {
  background: linear-gradient(
    180deg,
    var(--ds-surface-tint) 0%,
    var(--ds-surface) 100%
  );
  border-color: var(--ds-border);
  /* Recommended ("Empfohlen") tier — lifted on the z-axis via a heavier
     resting shadow so it reads as the most prominent card, ahead of the
     flat-ringed Agency tier. Elevation (not a transform) keeps it stable
     under the pricing grid's GSAP reveal/stagger animations. */
  box-shadow: var(--ds-shadow-lg);
}
.ds-card--featured:hover,
.ds-card--featured:focus-within {
  box-shadow:
    0 16px 32px rgba(var(--ds-blue-rgb), 0.16),
    0 32px 64px rgba(var(--ds-red-rgb), 0.12);
}

/* === Card Variants === */

/* Numbered card — renders its data-num attribute as a large ghost
   numeral in the top-right corner (reference §05 process cards). */
.ds-card--numbered {
  position: relative;
}

.ds-card--numbered::before {
  content: attr(data-num);
  position: absolute;
  top: var(--ds-space-3);
  right: var(--ds-space-5);
  font-size: var(--ds-text-section);
  font-weight: var(--ds-fw-black);
  color: var(--ds-blue);
  opacity: 0.12;
  pointer-events: none;
}

.ds-card--stat {
  align-items: flex-start;
}

.ds-card--stat .ds-card__icon {
  /* Unified icon signature (solid blue→purple gradient + white glyph) via the
       shared block. Only the stat-card-specific size stays here. */
  width: 36px;
  height: 36px;
  border-radius: var(--ds-radius-sm);
  font-size: var(--ds-text-lg);
}

.ds-card--stat .ds-card__label {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ds-tracking-meta);
  color: var(--ds-ink-mute);
  margin: 0;
}

.ds-card--stat .ds-card__value {
  font-size: 28px;
  font-weight: var(--ds-fw-black);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
  margin: 0;
  line-height: var(--ds-lh-tight);
}

.ds-card--stat .ds-card__context {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
  margin: 0;
}

.ds-card--stat .ds-card__action {
  margin-top: auto;
  padding-top: var(--ds-space-4);
}

.ds-card--feature {
  align-items: flex-start;
  gap: var(--ds-space-3);
}

/* .ds-card--feature .ds-card__icon — unified in the shared icon-tile block
   (solid blue→purple gradient + white glyph). Only the size override remains
   here; feature-cards keep the slightly-smaller 40×40 tile. */

.ds-card__title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
  line-height: 1.3;
  letter-spacing: var(--ds-tracking-tight);
}

.ds-card--feature .ds-card__title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
  line-height: 1.3;
}

.ds-card--feature .ds-card__body {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  line-height: var(--ds-lh-prose);
  margin: 0;
}

.ds-card--pricing {
  padding: var(--ds-space-6);
  gap: var(--ds-space-4);
}

.ds-card--pricing .ds-card__tier-tag {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ds-blue);
}

.ds-card--pricing.ds-card--featured .ds-card__tier-tag {
  color: var(
    --ds-danger
  ); /* AA-compliant dark red for text-readability on light tint */
}

.ds-card--pricing .ds-card__price {
  font-size: 36px;
  font-weight: var(--ds-fw-black);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
  line-height: 1;
  margin: 0;
}

.ds-card--pricing .ds-card__price small {
  font-size: 15px;
  font-weight: var(--ds-fw-medium);
  color: var(--ds-ink-mute);
  margin-left: var(--ds-space-0-5);
}

.ds-card--pricing .ds-card__credits {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  margin: 0;
}

.ds-card--pricing .ds-card__features {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  list-style: none;
  padding: 0;
  margin: var(--ds-space-2) 0 var(--ds-space-4);
}

.ds-card--pricing .ds-card__features li {
  padding-left: var(--ds-space-5);
  position: relative;
  line-height: var(--ds-lh-base);
}

.ds-card--pricing .ds-card__features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--ds-success);
  font-weight: var(--ds-fw-black);
}

.ds-card--pricing .ds-card__features li.ds-card__features-no {
  color: var(--ds-ink-mute);
}

.ds-card--pricing .ds-card__features li.ds-card__features-no::before {
  content: "✗";
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-bold);
}

.ds-card--pricing .ds-button {
  margin-top: auto;
}

/* Absolute-positioned badge inside a pricing card (plan status / tier label). */
.ds-card__badge {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
}

/* Pricing-card header row: tier tag left, plan badge right. The badge
   participates in flow here, so it can never overlap the tier-tag text on
   narrow cards (the absolute placement above did exactly that at 1440px). */
.ds-card__plan-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-2);
  /* Reserve the badge height even on badge-less cards so the four cards
       in a pricing row keep their tier tags on one visual line. */
  min-height: 24px;
}

.ds-card__plan-head .ds-card__badge {
  position: static;
  flex-shrink: 0;
}

/* Plan name label inside a ds-card--pricing card (eyebrow-style text above price). */
.ds-card--pricing .ds-card__name {
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink-mute);
  text-transform: uppercase;
  letter-spacing: var(--ds-tracking-meta);
  margin-bottom: var(--ds-space-2);
}

/* CTA wrapper inside a pricing card; pushes the button to the bottom of the
   flex column so all cards in a row align their CTAs. */
.ds-card--pricing .ds-card__cta {
  margin-top: auto;
}

/* Top-up package grid — auto-fit distributes all five packages evenly
   (5-up on desktop) instead of the orphaning fixed 4-column row. */
.ds-topup-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--ds-space-4);
}

@media (max-width: 575px) {
  .ds-topup-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* An odd package count would orphan the last card half-width. */
  .ds-topup-grid > .ds-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* Two cards per row leave the buy button barely 80px of label width inside
     a 24px-padded card, and a .ds-button label can neither wrap nor
     ellipsize. The tighter inline padding buys the ~24px that keep the label
     intact down to 320px viewports. */
  .ds-topup-grid > .ds-card--pricing {
    padding-inline: var(--ds-space-3);
  }
}

.ds-card--pricing .ds-card__topup-price {
  color: var(--ds-blue);
  font-size: clamp(1.25rem, 3vw, 1.5rem);
  font-weight: var(--ds-fw-black);
  margin: var(--ds-space-2) 0;
  letter-spacing: -0.01em;
}

/* Active-plan variant — brand-blue border ring to signal the subscriber's
   current tier. Green is not part of the plan-card palette (the brand ramp is
   blue/purple/red), so the active ring uses the primary brand blue. */
.ds-card--pricing.ds-card--current {
  border-color: var(--ds-blue);
  box-shadow: 0 0 0 4px rgba(var(--ds-blue-rgb), 0.12);
}

/* Agency-tier variant — purple border ring for the top-tier plan card. */
.ds-card--pricing.ds-card--ultimate {
  border-color: var(--ds-purple);
  box-shadow: 0 0 0 4px rgba(var(--ds-purple-rgb), 0.12);
}

.ds-card--content {
  gap: 0;
}

.ds-card--content .ds-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
  padding-bottom: var(--ds-space-3);
  border-bottom: 1px solid var(--ds-border-subtle);
  margin-bottom: var(--ds-space-4);
}

.ds-card--content .ds-card__header h2,
.ds-card--content .ds-card__header h3 {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
  letter-spacing: var(--ds-tracking-tight);
}

.ds-card--content .ds-card__body {
  flex: 1;
}

.ds-card--usecase .ds-card__avatar {
  width: 48px;
  height: 48px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-gradient-brand-soft);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ds-blue);
  font-size: 20px;
  font-weight: var(--ds-fw-bold);
}

.ds-card--usecase .ds-card__tag {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ds-blue);
}

.ds-card--usecase .ds-card__metric {
  font-size: 22px;
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  letter-spacing: var(--ds-tracking-tight);
}

.ds-card--lead {
  flex-direction: column;
  align-items: stretch;
  gap: var(--ds-space-3);
  padding: var(--ds-space-6) var(--ds-space-5);
  height: 100%;
}

.ds-card--lead .ds-card__title {
  font-size: var(--ds-text-body);
  line-height: 1.3;
  min-height: 2.6em;
}

.ds-card--lead .ds-button {
  margin-top: auto;
}

.ds-card--lead.ds-card--lead-blurred .ds-lead-contact {
  filter: blur(4px);
  user-select: none;
  pointer-events: none;
}

.ds-card__eyebrow {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ds-blue);
  margin: 0;
}

.ds-card__title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
}

.ds-card__title-row .ds-card__title {
  margin: 0;
}

.ds-card__lock {
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-lg);
  flex-shrink: 0;
}

.ds-card__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-2);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
}

.ds-card__meta-item {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
}

.ds-card__meta-item .bi {
  color: var(--ds-blue);
  font-size: var(--ds-text-body-sm);
}

.ds-card__meta-sep {
  color: var(--ds-ink-mute);
  opacity: 0.6;
}

.ds-card__score {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 4px var(--ds-space-3);
  padding: var(--ds-space-3) var(--ds-space-4);
  background: var(--ds-surface-tint);
  border-radius: var(--ds-radius-sm);
}

.ds-card__score-label {
  grid-column: 1 / 2;
  grid-row: 1 / 2;
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}

.ds-card__score-value {
  grid-column: 2 / 3;
  grid-row: 1 / 3;
  align-self: center;
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--ds-tracking-tight);
}

.ds-card__score-bar {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
  height: 6px;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-blue-rgb), 0.12);
  overflow: hidden;
}

.ds-card__score-bar-fill {
  height: 100%;
  background: var(--ds-gradient-brand);
  border-radius: var(--ds-radius-full);
}

.ds-card__highlight {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-2);
  padding: var(--ds-space-3) var(--ds-space-4);
  background: var(--ds-surface-tint);
  border-radius: var(--ds-radius-sm);
  border-left: 3px solid var(--ds-blue);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-prose);
  margin: 0;
  min-height: 5.5em;
}

.ds-card__highlight .bi {
  color: var(--ds-blue);
  font-size: var(--ds-text-body);
  flex-shrink: 0;
  margin-top: var(--ds-space-0-5);
}

.ds-card__locked-fields {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
  padding: var(--ds-space-3) 0 0;
  border-top: 1px dashed var(--ds-border-subtle);
}

.ds-card__locked-fields > span {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  padding: var(--ds-space-1) var(--ds-space-2-5);
  border-radius: var(--ds-radius-full);
  background: var(--ds-surface-muted);
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-semi);
}

.ds-card__locked-fields .bi {
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-eyebrow);
}

.ds-sample-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--ds-space-5);
  margin-top: var(--ds-space-8);
}

@media (max-width: 767px) {
  .ds-sample-grid {
    grid-template-columns: 1fr;
    gap: var(--ds-space-4);
  }
}

.ds-section-cta {
  margin-top: var(--ds-space-12);
  padding: var(--ds-space-8) var(--ds-space-6);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-sm);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ds-space-3);
}

.ds-section-cta h3 {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
  margin: 0;
}

.ds-section-cta p {
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body);
  margin: 0;
  max-width: 560px;
}

.ds-section-cta .ds-button {
  margin-top: var(--ds-space-2);
}

.ds-text-muted {
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-body-sm);
}

.ds-hero {
  position: relative;
  padding: clamp(48px, 8vw, 96px) var(--ds-space-6);
  overflow: hidden;
  isolation: isolate;
}

.ds-hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.ds-hero__content,
.ds-hero__copy {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-4);
}

/* The flex column would stretch the inline eyebrow pill to the full hero
   width (default align-items: stretch) — keep it hugging its content and
   centered like the rest of the hero copy. */
.ds-hero__content > .ds-eyebrow {
  align-self: center;
}

.ds-hero__title {
  font-size: var(--ds-text-hero-standard);
  font-weight: var(--ds-fw-black);
  line-height: var(--ds-lh-tight);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
  margin: 0;
  text-wrap: balance;
  /* This heading renders third-party data at up to 48px: the scraped
     company name on the unlocked-lead detail page and the user's own
     e-mail on the dashboard. German compounds and address-style e-mails
     offer no break opportunity, and the page-level `overflow-x: clip`
     would then silently cut the name off at the viewport edge rather than
     scroll. Same reasoning as the lead-table card view, which already
     carries this rule at a third of the size. */
  overflow-wrap: anywhere;
}

.ds-hero__lead {
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-prose);
  color: var(--ds-ink-soft);
  max-width: 640px;
  margin: 0;
}

.ds-hero__actions {
  display: flex;
  gap: var(--ds-space-3);
  flex-wrap: wrap;
  margin-top: var(--ds-space-2);
}

.ds-hero--standard {
  background: var(--ds-white);
  padding-top: var(--ds-space-10);
  padding-bottom: var(--ds-space-10);
}

/* The marketing standard-hero sits on a plain white surface; its atmosphere
   comes from the surrounding section, not from the hero itself. */
.ds-layout-shell--marketing .ds-hero--standard {
  background: var(--ds-white);
}

.ds-hero--dramatic {
  background: linear-gradient(
    135deg,
    var(--ds-surface-dark) 0%,
    var(--ds-surface-dark-2) 50%,
    var(--ds-surface-dark-violet) 100%
  );
  color: var(--ds-white);
  /* Hero fills the remaining viewport height after the sticky opaque header.
       Flow is standard (no negative margin, no pin-spacer) so the eyebrow never
       hides behind the now-opaque white-glass header. */
  min-height: calc(100svh - var(--ds-site-header-h, 80px));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: var(--ds-space-10);
  padding-bottom: var(--ds-space-10);
}

@supports not (min-height: 100svh) {
  .ds-hero--dramatic {
    min-height: calc(100vh - var(--ds-site-header-h, 80px));
  }
}

.ds-hero--dramatic .ds-hero__title {
  font-size: var(--ds-text-hero-dramatic);
  color: var(--ds-white);
}

.ds-hero--dramatic .ds-hero__lead {
  color: rgba(var(--ds-white-rgb), 0.78);
}

.ds-hero--dramatic .ds-hero__bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    conic-gradient(
      from 0deg at 50% 50%,
      rgba(var(--ds-blue-rgb), 0.28) 0deg,
      rgba(var(--ds-purple-rgb), 0.2) 90deg,
      rgba(var(--ds-red-rgb), 0.22) 180deg,
      rgba(var(--ds-blue-rgb), 0.28) 360deg
    ),
    radial-gradient(
      circle at 50% 50%,
      transparent 0%,
      var(--ds-surface-dark) 80%
    );
}

.ds-hero--dramatic .ds-hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(
    circle at 50% 50%,
    black 0%,
    transparent 80%
  );
  mask-image: radial-gradient(circle at 50% 50%, black 0%, transparent 80%);
}

.ds-hero__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--ds-space-10);
  max-width: 1200px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

@media (min-width: 992px) {
  .ds-hero__grid {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--ds-space-16);
    align-items: center;
  }
}

/* === Sections === */

.ds-section {
  position: relative;
  width: 100%;
  padding: clamp(48px, 8vw, 96px) var(--ds-space-6);
  overflow: hidden;
}

.ds-section__inner {
  max-width: 1200px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

.ds-section__title {
  font-size: var(--ds-text-section);
  font-weight: var(--ds-fw-black);
  line-height: var(--ds-lh-tight);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
  text-align: center;
  margin: 0 0 var(--ds-space-4);
  text-wrap: balance;
}

.ds-section__lead {
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-prose);
  color: var(--ds-ink-soft);
  text-align: center;
  max-width: 720px;
  margin: 0 auto var(--ds-space-8);
}

.ds-section--light {
  background: var(--ds-surface-tint);
}
.ds-section--tint {
  background: var(--ds-surface-muted);
}

.ds-section--atmo {
  background: linear-gradient(
    180deg,
    var(--ds-surface-tint) 0%,
    var(--ds-surface-muted) 100%
  );
}

.ds-section--atmo::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      circle at 20% 10%,
      rgba(var(--ds-blue-rgb), 0.1) 0%,
      transparent 45%
    ),
    radial-gradient(
      circle at 80% 90%,
      rgba(var(--ds-red-rgb), 0.08) 0%,
      transparent 45%
    );
  pointer-events: none;
}

.ds-section--dark {
  background: var(--ds-surface-dark-2);
  color: var(--ds-white);
}

.ds-section--dark .ds-section__title {
  color: var(--ds-white);
}
.ds-section--dark .ds-section__lead {
  color: rgba(var(--ds-white-rgb), 0.78);
}

.ds-section--dark-pattern {
  background:
    radial-gradient(
      ellipse 70% 50% at 80% 0%,
      rgba(var(--ds-purple-rgb), 0.25),
      transparent 60%
    ),
    radial-gradient(
      ellipse 60% 40% at 20% 100%,
      rgba(var(--ds-blue-rgb), 0.22),
      transparent 65%
    ),
    linear-gradient(180deg, #0c0e22 0%, #080a1c 100%);
  color: var(--ds-white);
  isolation: isolate;
}

.ds-section--dark-pattern::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(
    circle at 50% 50%,
    black 0%,
    transparent 75%
  );
  mask-image: radial-gradient(circle at 50% 50%, black 0%, transparent 75%);
  opacity: 0.6;
  pointer-events: none;
  z-index: 0;
}

.ds-section--dark-pattern .ds-section__title {
  color: var(--ds-white);
}
.ds-section--dark-pattern .ds-section__lead {
  color: rgba(var(--ds-white-rgb), 0.78);
}

/* === CTA-Band ===
   Redesigned footer CTA-band; supersedes the earlier .ds-cta-band block (the
   one using the legacy ds-op-gradient-dark background and fixed 120px padding).
   The later declaration wins by source order. */

.ds-cta-band {
  position: relative;
  /* Reduced ~1/3 from the previous pass — still presents but no longer
       dominates the footer. */
  padding: clamp(52px, 6.5vw, 92px) var(--ds-space-6);
  background: linear-gradient(
    135deg,
    var(--ds-surface-dark) 0%,
    var(--ds-surface-dark-2) 50%,
    var(--ds-surface-dark-violet) 100%
  );
  color: var(--ds-white);
  overflow: hidden;
  isolation: isolate;
}

.ds-cta-band__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.ds-cta-band__bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      circle at 15% 20%,
      rgba(var(--ds-blue-rgb), 0.4) 0%,
      transparent 40%
    ),
    radial-gradient(
      circle at 85% 80%,
      rgba(var(--ds-red-rgb), 0.3) 0%,
      transparent 40%
    );
}

.ds-cta-band__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--ds-white-rgb), 0.04) 1px, transparent 1px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(
    circle at 50% 50%,
    black 0%,
    transparent 75%
  );
  mask-image: radial-gradient(circle at 50% 50%, black 0%, transparent 75%);
}

.ds-cta-band__content {
  position: relative;
  z-index: 1;
  max-width: 960px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-5);
  align-items: flex-start;
  text-align: center;
}

@media (min-width: 768px) {
  .ds-cta-band__content {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-space-10);
  }
}

.ds-cta-band__title {
  /* Scaled down ~30% from the previous 32-56px range. */
  font-size: clamp(24px, 3vw, 38px);
  font-weight: var(--ds-fw-black);
  line-height: var(--ds-lh-tight);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-white);
  margin: var(--ds-space-1) 0 var(--ds-space-3);
}

.ds-cta-band__lead {
  font-size: var(--ds-text-body-sm);
  color: rgba(var(--ds-white-rgb), 0.82);
  margin: 0;
  max-width: 540px;
  line-height: 1.55;
}

.ds-cta-band__actions {
  display: flex;
  gap: var(--ds-space-2);
  flex-wrap: wrap;
  flex-shrink: 0;
}

/* === Form Controls === */

.ds-form-field {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-1);
  margin-bottom: var(--ds-space-4);
}

.ds-form-label {
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink);
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-0-5);
}

.ds-form-control {
  display: block;
  width: 100%;
  padding: var(--ds-space-2-5) var(--ds-space-3-5);
  font-family: inherit;
  font-size: var(--ds-text-body);
  line-height: 1.4;
  color: var(--ds-ink);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm);
  transition:
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-form-control:focus-visible,
.ds-form-control:focus {
  outline: none;
  border-color: var(--ds-blue);
  box-shadow: var(--ds-shadow-focus);
}

.ds-form-control:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background: var(--ds-surface-tint);
}

/* Placeholders are text and fall under the 4.5:1 floor like any other. With
   no rule at all the browser default applied, which differs per engine and
   lands close to the limit in Chrome. --ds-ink-mute is the same muted ink
   the crispy bridge already uses, so both paths now read identically. */
.ds-form-control::placeholder {
  color: var(--ds-ink-mute);
  opacity: 1;
}

.ds-form-control--error {
  border-color: var(--ds-danger);
  background: var(--ds-danger-tint);
  box-shadow: var(--ds-shadow-field-danger);
}

.ds-form-control--error:focus-visible,
.ds-form-control--error:focus {
  border-color: var(--ds-danger);
  box-shadow: var(--ds-shadow-focus-danger);
}

.ds-form-control--success {
  border-color: var(--ds-success);
  background: var(--ds-success-tint);
}

.ds-form-control--success:focus-visible,
.ds-form-control--success:focus {
  border-color: var(--ds-success);
  box-shadow: var(--ds-shadow-focus-success);
}

.ds-form-help {
  margin: var(--ds-space-1) 0 0;
  font-size: var(--ds-text-caption);
  line-height: var(--ds-lh-base);
  color: var(--ds-ink-mute);
}

.ds-form-help--error {
  color: var(--ds-danger);
  font-weight: var(--ds-fw-medium);
}

textarea.ds-form-control {
  resize: vertical;
  min-height: 96px;
}

/* ============================================================================
 * ds-chip-input — progressive-enhancement multi-value picker (wishes form)
 * JS (wishes_form.js) hides the backing textarea and renders selected values
 * as removable chips above a single-line entry input.
 * ==========================================================================*/
.ds-chip-input__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
  margin-bottom: var(--ds-space-2);
}

.ds-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-1) var(--ds-space-3);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-full);
  background: var(--ds-surface-tint);
  color: var(--ds-ink);
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-base);
}

.ds-chip__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: var(--ds-radius-full);
  background: transparent;
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-body);
  line-height: 1;
  cursor: pointer;
}

.ds-chip__remove:hover {
  color: var(--ds-danger);
}

.ds-chip__remove:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* Grow the remove button's tap target to the 44px touch floor below 768px
 * without enlarging the visible glyph: a transparent, centered overlay
 * extends the clickable area while the chip layout stays compact. */
@media (max-width: 767px) {
  .ds-chip__remove {
    position: relative;
  }

  .ds-chip__remove::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* ============================================================================
 * ds-check — canonical checkbox / radio / switch family (C2.2)
 * Replaces raw Bootstrap .form-check markup. The wrapping <label> carries the
 * hit area, so no for/id pairing is required:
 *   <label class="ds-check">
 *       <input class="ds-check__input" type="checkbox">
 *       <span class="ds-check__label">Text</span>
 *   </label>
 * Switch variant: <label class="ds-check ds-check--switch"> with the same
 * children. Below 768px the row grows to the 44px touch floor while the
 * visible control stays 24px.
 * ========================================================================== */
.ds-check {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-3);
  cursor: pointer;
  margin: 0;
}

/* Label-less variant for table row selection — the aria-label on the
   input carries the accessible name, so no gap is needed. */
.ds-check--bare {
  display: inline-flex;
  gap: 0;
  vertical-align: middle;
}

.ds-check__input {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin: 0;
  background-color: var(--ds-surface);
  border: 1px solid var(--ds-border-strong);
  border-radius: var(--ds-radius-xs);
  cursor: pointer;
  transition:
    background-color var(--ds-dur-fast) var(--ds-ease-out),
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-check__input:hover {
  border-color: var(--ds-blue);
}

.ds-check__input:focus-visible {
  outline: none;
  border-color: var(--ds-blue);
  box-shadow: var(--ds-shadow-focus);
}

/* The check glyph ships as an inline SVG data-URI (white stroke) — same
   asset pattern as the select chevron above; not a component color literal. */
.ds-check__input:checked {
  background-color: var(--ds-blue);
  border-color: var(--ds-blue);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 14px 14px;
}

.ds-check__input[type="radio"] {
  border-radius: var(--ds-radius-full);
}

/* Radios keep a surface-colored dot punched out of the filled circle. */
.ds-check__input[type="radio"]:checked {
  background-image: none;
  box-shadow: inset 0 0 0 6px var(--ds-blue);
  background-color: var(--ds-surface);
}

/* A checked box is filled with the very colour the focus ring is drawn in —
   without the inset white band the ring reads as a blue square inside a blue
   square. This is exactly the case --ds-shadow-focus-on-brand exists for. */
.ds-check__input:checked:focus-visible {
  box-shadow: var(--ds-shadow-focus-on-brand);
}

.ds-check__input[type="radio"]:checked:focus-visible {
  box-shadow:
    inset 0 0 0 6px var(--ds-blue),
    var(--ds-shadow-focus-on-brand);
}

.ds-check__input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background-color: var(--ds-surface-tint);
}

/* Checked + disabled keeps the blue fill (dimmed via opacity) so the white
   check glyph stays visible instead of washing out on the tint surface. */
.ds-check__input:checked:disabled {
  background-color: var(--ds-blue);
  border-color: var(--ds-blue);
}

.ds-check__input[type="radio"]:checked:disabled {
  background-color: var(--ds-surface);
}

.ds-check__input:disabled ~ .ds-check__label {
  opacity: 0.6;
  cursor: not-allowed;
}

.ds-check__label {
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-base);
  color: var(--ds-ink);
  /* Vertically centers the first label line against the 24px control. */
  padding-top: var(--ds-space-0-5);
}

/* The consent labels are the one place in the product where a link sits inside
   running body copy, and there it was marked by colour alone: --ds-blue against
   --ds-ink measures 1.92:1, well under the 3:1 that WCAG 1.4.1 requires before
   colour may carry the distinction by itself. Underlining is also what makes
   these two links aimable now that they no longer carry an oversized hit box. */
.ds-check__label a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Switch — pill track with a sliding knob, same input element underneath. */
.ds-check--switch .ds-check__input {
  position: relative;
  width: 44px;
  border-radius: var(--ds-radius-full);
  background-color: var(--ds-surface-muted);
  border-color: var(--ds-border);
}

.ds-check--switch .ds-check__input::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-surface);
  box-shadow: var(--ds-shadow-sm);
  border: 1px solid var(--ds-border-subtle);
  transition: transform var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-check--switch .ds-check__input:checked {
  background-color: var(--ds-blue);
  border-color: var(--ds-blue);
  background-image: none;
}

.ds-check--switch .ds-check__input:checked::before {
  transform: translateX(20px);
}

/* Same reasoning as the checked checkbox: the switch track carries the ring
   colour once it is on. */
.ds-check--switch .ds-check__input:checked:focus-visible {
  box-shadow: var(--ds-shadow-focus-on-brand);
}

/* Mobile touch floor: the full label row becomes the 44px hit area while
   the visible 24px control keeps the desktop proportions. */
@media (max-width: 767px) {
  .ds-check {
    align-items: center;
    min-height: 44px;
  }
  .ds-check__label {
    padding-top: 0;
  }
}

/* === Panels === */

.ds-panel {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  padding: var(--ds-space-5);
  box-shadow: var(--ds-shadow-sm);
}

.ds-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
  padding-bottom: var(--ds-space-3);
  border-bottom: 1px solid var(--ds-border-subtle);
  margin-bottom: var(--ds-space-4);
}

.ds-panel__header h3 {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
}

.ds-panel--sidebar {
  position: sticky;
  top: var(--ds-space-5);
  max-height: calc(100vh - 100px);
  overflow-y: auto;
}

/* === Settings Section + Danger Zone === */

.ds-settings-section {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  padding: var(--ds-space-5);
  margin-top: var(--ds-space-5);
  box-shadow: var(--ds-shadow-sm);
}

.ds-settings-section__header {
  padding-bottom: var(--ds-space-3);
  border-bottom: 1px solid var(--ds-border-subtle);
  margin-bottom: var(--ds-space-4);
}

.ds-settings-section__title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
}

.ds-settings-section--danger {
  border-color: var(--ds-danger);
  background: var(--ds-surface);
}

.ds-settings-section--danger .ds-settings-section__title {
  color: var(--ds-danger);
}

.ds-danger-block {
  padding: var(--ds-space-4);
  border: 1px solid var(--ds-danger-tint);
  border-radius: var(--ds-radius-sm);
  background: var(--ds-surface);
  margin-top: var(--ds-space-3);
}

.ds-danger-block + .ds-danger-block {
  margin-top: var(--ds-space-4);
}

.ds-danger-block h3 {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0 0 var(--ds-space-2);
}

.ds-danger-block p {
  color: var(--ds-ink-soft);
  margin: 0 0 var(--ds-space-3);
  line-height: var(--ds-lh-prose);
}

.ds-danger-block ul {
  margin: 0 0 var(--ds-space-3);
  padding-left: var(--ds-space-5);
  color: var(--ds-ink-soft);
}

/* === Empty State === */

.ds-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--ds-space-10) var(--ds-space-6);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-sm);
  gap: var(--ds-space-3);
}

.ds-empty-state__illustration {
  width: 64px;
  height: 64px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--ds-radius-full);
  background: var(--ds-gradient-brand-soft);
  color: var(--ds-blue);
  font-size: 28px;
  margin-bottom: var(--ds-space-2);
}

.ds-empty-state__title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
}

.ds-empty-state__body {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  max-width: 420px;
  margin: 0;
  line-height: var(--ds-lh-prose);
}

/* Success-tinted illustration tile used on the checkout-success page. */
.ds-empty-state__illustration--success {
  background: var(--ds-success-tint);
  color: var(--ds-success);
}

/* Button-row inside an empty state. */
.ds-empty-state__actions {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 0.5rem;
}

/* === Toast === */

/* === Trust Strip === */

.ds-trust-strip {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--ds-space-6);
  padding: var(--ds-space-4) var(--ds-space-6);
  background: var(--ds-surface-dark);
  border-top: 1px solid rgba(var(--ds-white-rgb), 0.04);
  font-size: var(--ds-text-caption);
  color: rgba(var(--ds-white-rgb), 0.55);
  flex-wrap: wrap;
}

/* === Compare Table === */

.ds-compare-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  color: var(--ds-ink);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  /* overflow: visible keeps the FAVORIT badge readable above the header.
       Corner cells below carry their own border-radius so the table still
       reads as a rounded block. */
  overflow: visible;
  box-shadow: var(--ds-shadow-sm);
}

.ds-compare-caption {
  caption-side: bottom;
  padding: var(--ds-space-3) var(--ds-space-4) 0;
  font-size: var(--ds-text-caption);
  line-height: var(--ds-lh-base);
  /* From the table breakpoint upwards the caption sits inside the white table
     block, so it needs light-surface ink. Below that breakpoint the stacked
     layout moves it onto the dark section surface, where the on-dark override
     further down restores readability. */
  color: var(--ds-ink-mute);
  text-align: left;
}

.ds-compare-table th,
.ds-compare-table td {
  padding: var(--ds-space-3) var(--ds-space-4);
  text-align: left;
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink);
  border-bottom: 1px solid var(--ds-border-subtle);
}

.ds-compare-table th {
  background: var(--ds-surface-tint);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  text-transform: uppercase;
  font-size: var(--ds-text-caption);
  letter-spacing: var(--ds-tracking-meta);
}

/* Round the four corner cells to match the table's 14px radius. Without this
   the corner cells render as sharp rectangles that poke out of the rounded
   table outline ("Spitze" the user noticed above the Merkmal cell). */
.ds-compare-table thead tr:first-child th:first-child {
  border-top-left-radius: var(--ds-radius-md);
}
.ds-compare-table thead tr:first-child th:last-child {
  border-top-right-radius: var(--ds-radius-md);
}
.ds-compare-table tbody tr:last-child th:first-child {
  border-bottom-left-radius: var(--ds-radius-md);
}
.ds-compare-table tbody tr:last-child td:last-child {
  border-bottom-right-radius: var(--ds-radius-md);
}
.ds-compare-table tbody tr:last-child th,
.ds-compare-table tbody tr:last-child td {
  border-bottom: 0;
}

/* LeadSuche column: subtle tinted bg + bold brand-blue text so the column
   reads as the Favorite without needing a loud gradient. */
.ds-compare-table .ds-compare-col--highlight {
  background: rgba(var(--ds-blue-rgb), 0.05);
}

/* Reset the subtle tint applied by .ds-compare-col--highlight so body cells
   stay white; only the thead header cell gets the richer brand tint (below). */
.ds-compare-table th.ds-compare-table__col--highlight,
.ds-compare-table td.ds-compare-table__col--highlight,
.ds-compare-table__col--highlight {
  background: transparent !important;
  font-weight: var(--ds-fw-black);
  color: var(--ds-blue);
  border-left: 2px solid var(--ds-blue);
  border-right: 2px solid var(--ds-blue);
}

.ds-compare-table thead th.ds-compare-table__col--highlight {
  /* Header cell gets a richer tint so the LeadSuche column header pops. */
  background: rgba(var(--ds-blue-rgb), 0.1) !important;
  color: var(--ds-blue);
  font-weight: var(--ds-fw-black);
  letter-spacing: 0.02em;
  position: relative;
}

/* "Favorit"-Badge sitting above the LeadSuche header. Pulled out of the
   table's overflow-clipped box via high z-index + the parent needs an
   explicit stacking-context override (see .ds-compare-wrap below). */
.ds-compare-table thead th.ds-compare-table__col--highlight::before {
  content: "FAVORIT";
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  padding: 3px 12px;
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  font-size: 10px;
  font-weight: var(--ds-fw-black);
  letter-spacing: var(--ds-tracking-eyebrow);
  border-radius: var(--ds-radius-full);
  white-space: nowrap;
  box-shadow: 0 6px 14px rgba(var(--ds-blue-rgb), 0.45);
  z-index: 20;
  pointer-events: none;
}

/* Compare-wrap: allow the FAVORIT-Badge to extend above the table box. */
.ds-compare-wrap {
  /* overflow stays visible so the FAVORIT badge can sit above the table
       edge; the <768px collapse swaps this for a stacked card layout. */
  overflow: visible;
  position: relative;
  border-radius: var(--ds-radius-lg);
  background: linear-gradient(
    180deg,
    rgba(var(--ds-white-rgb), 0.035),
    rgba(var(--ds-white-rgb), 0.015)
  );
  border: 1px solid var(--ds-surface-dark-border);
  box-shadow:
    0 40px 80px rgba(var(--ds-black-rgb), 0.4),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.06);
  padding: 0.5rem;
  padding-top: var(--ds-space-3-5);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* Row-level hover: light-grey tint across all non-highlight cells so the user
   can track the row they're reading. The highlight column stays transparent
   so the <col> gradient stays intact. */
.ds-compare-table tbody tr {
  transition: background-color 0.15s ease;
}
.ds-compare-table tbody tr:hover > th,
.ds-compare-table tbody tr:hover > td:not(.ds-compare-table__col--highlight) {
  background: rgba(var(--ds-blue-rgb), 0.06);
}
.ds-compare-table tbody tr:hover > td.ds-compare-table__col--highlight {
  /* Row-hover keeps the highlight column cell transparent so the col tint
       stays visible; slightly deeper blue wash on hover. */
  box-shadow: inset 0 0 0 9999px rgba(var(--ds-blue-rgb), 0.04);
}

/* Mobile card collapse (<768px): the five provider columns cannot fit a
   phone, so each row becomes a stacked card of label/value pairs fed by the
   cells' data-col attributes. Scoped to .ds-compare-wrap (the marketing
   table); bare reference demos use the ds-table-wrap scroll strategy. */
@media (max-width: 767px) {
  .ds-compare-wrap {
    background: transparent;
    border: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0;
  }
  /* Flex column instead of display:block so the bottom caption can be
       ordered after the row cards despite being first in the DOM. */
  .ds-compare-wrap .ds-compare-table {
    display: flex;
    flex-direction: column;
    background: transparent;
    border: none;
    box-shadow: none;
  }
  .ds-compare-wrap .ds-compare-table colgroup,
  .ds-compare-wrap .ds-compare-table thead {
    display: none;
  }
  .ds-compare-wrap .ds-compare-table tbody,
  .ds-compare-wrap .ds-compare-table tr,
  .ds-compare-wrap .ds-compare-table th,
  .ds-compare-wrap .ds-compare-table td {
    display: block;
    min-width: 0;
    width: auto;
  }
  .ds-compare-wrap .ds-compare-table tbody tr {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border-subtle);
    border-radius: var(--ds-radius-md);
    padding: var(--ds-space-4);
    margin-bottom: var(--ds-space-3);
    box-shadow: var(--ds-shadow-sm);
  }
  .ds-compare-wrap .ds-compare-table tbody th {
    background: transparent;
    padding: 0 0 var(--ds-space-2);
    margin-bottom: var(--ds-space-2);
    font-size: var(--ds-text-body);
    text-transform: none;
    letter-spacing: 0;
    border-bottom: 1px solid var(--ds-border-subtle);
  }
  .ds-compare-wrap .ds-compare-table tbody td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--ds-space-4);
    padding: var(--ds-space-1) 0;
    border-bottom: none;
    text-align: right;
  }
  .ds-compare-wrap .ds-compare-table tbody td::before {
    content: attr(data-col);
    font-size: var(--ds-text-caption);
    font-weight: var(--ds-fw-semi);
    color: var(--ds-ink-mute);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    text-align: left;
    flex-shrink: 0;
  }
  .ds-compare-wrap .ds-compare-table td.ds-compare-table__col--highlight {
    border-left: none;
    border-right: none;
  }
  .ds-compare-wrap .ds-compare-caption {
    display: block;
    order: 1;
    padding: 0;
    color: rgba(var(--ds-white-rgb), 0.55);
  }
}

/* === Link-Card === */

.ds-link-card {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  padding: var(--ds-space-4);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-sm);
  text-decoration: none;
  color: var(--ds-ink);
  transition: all var(--ds-dur-base) var(--ds-ease-out);
  position: relative;
  overflow: hidden;
}

.ds-link-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--ds-gradient-brand);
  opacity: 0;
  transition: opacity var(--ds-dur-base) var(--ds-ease-out);
}

.ds-link-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--ds-shadow-md);
  border-color: var(--ds-border);
}

.ds-link-card:hover::before {
  opacity: 1;
}

.ds-link-card__icon {
  /* Same unified solid gradient + white glyph as all other icon-tiles
       across the project. */
  width: 36px;
  height: 36px;
  border-radius: var(--ds-radius-sm);
  background: var(--ds-gradient-icon-tile);
  color: var(--ds-white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--ds-text-lg);
  flex-shrink: 0;
  box-shadow: var(--ds-shadow-icon-tile);
  transition:
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.4s ease;
}
.ds-card:hover .ds-link-card__icon {
  transform: scale(1.08) rotate(-3deg);
  box-shadow: 0 14px 28px rgba(var(--ds-blue-rgb), 0.35);
}

.ds-link-card__body {
  flex: 1;
  min-width: 0;
}

.ds-link-card__title {
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0 0 var(--ds-space-0-5);
}

.ds-link-card__desc {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
  margin: 0;
}

/* === Sticky CTA === */

.ds-sticky-cta {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 40;
  padding: var(--ds-space-3) var(--ds-space-5);
  background: var(--ds-surface-dark);
  color: var(--ds-white);
  border: 1px solid var(--ds-surface-dark-border);
  border-radius: var(--ds-radius-md);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--ds-space-4);
  box-shadow: 0 -4px 20px rgba(var(--ds-blue-rgb), 0.2);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  max-width: 760px;
  margin-inline: auto;
  transform: translateY(100%);
  opacity: 0;
  transition: transform var(--ds-dur-base) var(--ds-ease-out);
}

.ds-sticky-cta.is-visible {
  transform: translateY(0);
  opacity: 1;
}

/* Small viewports: the bar wraps into two rows, so gap and padding tighten.
   This block has to sit AFTER the base definition above — media queries do not
   raise specificity, and while it stood earlier in the file the base padding
   won and the bar kept desktop spacing while wrapping. Values pulled onto the
   spacing scale (8 px / 12 px) in the same move. */
@media (max-width: 575px) {
  .ds-sticky-cta {
    flex-wrap: wrap;
    gap: var(--ds-space-2);
    padding: var(--ds-space-3);
  }
  .ds-sticky-cta-text {
    flex: 1 0 100%;
  }
}

/* === Prose (for legal pages) === */

.ds-prose {
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-prose);
  color: var(--ds-ink-soft);
}

.ds-prose h2,
.ds-prose h3 {
  color: var(--ds-ink);
  margin: var(--ds-space-8) 0 var(--ds-space-3);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-tight);
}

.ds-prose h2 {
  font-size: var(--ds-text-subsection);
}
.ds-prose h3 {
  font-size: var(--ds-text-lg);
}
.ds-prose p {
  margin: 0 0 var(--ds-space-4);
}
.ds-prose ul,
.ds-prose ol {
  margin: 0 0 var(--ds-space-4) var(--ds-space-5);
}
.ds-prose a {
  color: var(--ds-blue);
  text-decoration: underline;
}
.ds-prose strong {
  color: var(--ds-ink);
  font-weight: var(--ds-fw-bold);
}

/* Prose tables — blog-article bodies author bare <table> elements (no class),
   which would otherwise render as unstyled browser-default tables clashing
   with the surrounding prose. Mirror the canonical .ds-table skin (gradient
   header, row hover, borderless last row) using tokens so article comparison
   tables read as first-class DS components. */
.ds-prose table {
  width: 100%;
  margin: 0 0 var(--ds-space-5);
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  overflow: hidden;
  font-size: var(--ds-text-body-sm);
}
/* Below the tablet breakpoint the article comparison tables are wider than
   the prose column (measured: 566-629px intrinsic in a 327px container)
   (WCAG 1.4.10 Reflow). Every article table therefore sits in a
   `.ds-prose-table` wrapper that scrolls instead of the table itself: the
   table keeps `display: table` and its row/cell semantics in every engine,
   and the wrapper carries `tabindex="0"`, `role="region"` and an
   `aria-label` in the article file, so keyboard users can focus it and
   scroll the overflow in WebKit too, where scrollers are not focusable on
   their own. The table cannot shrink below its content width, so on a phone
   it overflows the wrapper and the wrapper scrolls. */
.ds-prose-table {
  margin: 0 0 var(--ds-space-5);
  overflow-x: auto;
}
.ds-prose-table > table {
  margin: 0;
}
.ds-prose-table:focus-visible {
  outline: 3px solid var(--ds-blue);
  outline-offset: 3px;
}

.ds-prose th,
.ds-prose td {
  padding: 0.75rem 1rem;
  text-align: left;
  vertical-align: top;
}
.ds-prose thead th {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.04),
    rgba(var(--ds-purple-rgb), 0.03)
  );
  color: var(--ds-ink-mute);
  font-size: var(--ds-text-caption);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--ds-fw-bold);
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.1);
}
.ds-prose tbody td {
  color: var(--ds-ink-soft);
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.06);
}
.ds-prose tbody tr:last-child td {
  border-bottom: 0;
}

/* Legal-prose modifier — wraps the prose block in a premium card shell
   (surface background, subtle border, rounded corners) and adds the
   section-divider treatment (top-border on every h2 except the first)
   that makes long legal documents easier to scan. Absorbs all unique
   rules from the legacy .legal-prose class so that class can be dropped. */
.ds-prose--legal {
  padding: clamp(1.75rem, 4vw, 3rem);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-lg);
  box-shadow: var(--ds-shadow-sm);
}

.ds-prose--legal > :first-child {
  margin-top: 0;
}
.ds-prose--legal > :last-child {
  margin-bottom: 0;
}

.ds-prose--legal h2 {
  padding-top: var(--ds-space-6);
  border-top: 1px solid var(--ds-border);
}

.ds-prose--legal h2:first-of-type {
  padding-top: 0;
  border-top: none;
  margin-top: 0;
}

.ds-prose--legal ul li,
.ds-prose--legal ol li {
  margin-bottom: var(--ds-space-2);
}

.ds-prose--legal hr {
  margin: var(--ds-space-8) 0;
  border: 0;
  border-top: 1px dashed var(--ds-border);
}

/* Inline metadata line (Stand: date, last-updated notice) used at the top
   of legal documents. Lifted from inline style on the Stand: paragraph. */
.ds-prose-meta {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-mute);
}

/* === Site Header === */

.ds-site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  /* Static glass background — always visible. No scroll-based transition
       (the previous "becomes white on scroll" effect was confusing). */
  background: rgba(var(--ds-white-rgb), 0.88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: var(--ds-shadow-sm);
}

@supports not (backdrop-filter: blur(12px)) {
  .ds-site-header {
    background: var(--ds-surface);
  }
}

.ds-site-header__progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 2px;
  width: 0;
  background: var(--ds-gradient-brand);
  transition: width 50ms linear;
  z-index: 1;
}

.ds-site-header__inner {
  display: flex;
  align-items: center;
  /* Brand and actions are both flex-shrink:0, so the row has a hard 361px
     minimum and simply pushed past the viewport below 361px — clipped, not
     scrollable, because html/body carry overflow-x:clip. Gap and inline
     padding therefore scale fluidly down to their --ds-space-2 / -3 steps
     instead of stepping at a breakpoint: a new breakpoint below 575px would
     sit outside the documented canon, and the row needs to give continuously
     rather than at one width. Both clamps reach the token value at 640px. */
  gap: clamp(var(--ds-space-2), 2.5vw, var(--ds-space-5));
  padding: 18px clamp(var(--ds-space-3), 3.75vw, var(--ds-space-6));
  max-width: 1280px;
  margin: 0 auto;
}

.ds-site-header__inner--centered {
  justify-content: center;
}

.ds-site-header__brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: var(--ds-space-2);
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-black);
  color: var(--ds-blue);
  letter-spacing: var(--ds-tracking-tight);
  text-decoration: none;
  flex-shrink: 0;
}

.ds-site-header__logo {
  width: 28px;
  height: 28px;
}

/* Brand text next to the logo — inherits the brand link color/weight. */
.ds-site-header__wordmark {
  white-space: nowrap;
}

.ds-site-nav {
  display: flex;
  align-items: center;
  gap: var(--ds-space-1);
  flex: 1;
  justify-content: center;
}

.ds-site-nav__item {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  padding: var(--ds-space-2) var(--ds-space-3-5);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink-soft);
  text-decoration: none;
  border-radius: var(--ds-radius-sm);
  transition:
    color var(--ds-dur-fast) var(--ds-ease-out),
    background var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-site-nav__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-mute);
  transition:
    color var(--ds-dur-fast) var(--ds-ease-out),
    transform 0.35s var(--ds-ease-spring);
  flex-shrink: 0;
}

.ds-site-nav__label {
  line-height: 1;
}

.ds-site-nav__item:hover,
.ds-site-nav__item[aria-current="page"],
.ds-site-nav__item.is-active {
  color: var(--ds-blue);
}

.ds-site-nav__item:hover .ds-site-nav__icon,
.ds-site-nav__item[aria-current="page"] .ds-site-nav__icon,
.ds-site-nav__item.is-active .ds-site-nav__icon {
  /* Icon color picks up brand on hover/active — plus gentle scale/rotate
       micro-motion that matches the site's unified icon-hover signature. */
  color: var(--ds-blue);
  transform: scale(1.15) rotate(-5deg);
}

.ds-site-nav__item::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 2px;
  height: 2px;
  background: var(--ds-gradient-brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--ds-dur-base) var(--ds-ease-out);
  border-radius: var(--ds-radius-xs);
}

.ds-site-nav__item:hover::after,
.ds-site-nav__item[aria-current="page"]::after,
.ds-site-nav__item.is-active::after {
  transform: scaleX(1);
}

/* Mobile: icons stay, labels hide on narrow screens. Burger opens a full
   stack where both reappear. */
@media (max-width: 991px) {
  .ds-site-nav {
    display: none;
  }
  .ds-site-nav.is-open {
    display: flex;
    position: fixed;
    top: var(--ds-site-header-h, 80px);
    left: 0;
    right: 0;
    background: var(--ds-white);
    padding: var(--ds-space-4);
    flex-direction: column;
    align-items: stretch;
    gap: var(--ds-space-1);
    border-bottom: 1px solid var(--ds-border-subtle);
    box-shadow: 0 12px 32px rgba(var(--ds-blue-rgb), 0.1);
    z-index: 99;
  }
  .ds-site-nav.is-open .ds-site-nav__item {
    padding: var(--ds-space-3) var(--ds-space-4);
    font-size: var(--ds-text-body);
    gap: var(--ds-space-2-5);
    min-height: 44px;
  }
  .ds-site-nav.is-open .ds-site-nav__icon {
    width: 20px;
    height: 20px;
    font-size: var(--ds-text-lg);
  }
  .ds-site-nav.is-open .ds-site-nav__item::after {
    display: none;
  }
  .ds-site-nav.is-open .ds-site-nav__item:hover,
  .ds-site-nav.is-open .ds-site-nav__item.is-active {
    background: rgba(var(--ds-blue-rgb), 0.06);
  }
}

.ds-site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  flex-shrink: 0;
  /* Right-align the wallet + avatar cluster. On marketing pages the
       centered .ds-site-nav already pushes us right via flex:1, so this is
       redundant. On app pages the nav block is omitted from the DOM, and
       without margin-left:auto the actions would sit immediately next to
       the brand. `auto` handles both layouts cleanly. */
  margin-left: auto;
}

/* On very small viewports the two auth CTAs cause horizontal overflow.
   Hide the secondary "Anmelden" link — .ds-site-nav carries its own
   d-sm-none login entry below this breakpoint, which is what the burger
   menu opens (the header actions are not part of that menu)
   so the primary CTA always fits. */
@media (max-width: 575px) {
  .ds-site-header__actions .ds-button--ghost {
    display: none;
  }
  /* In the sticky bar the action label was set smaller than the explanatory
     text beside it — caption size against body-sm. Scoped to that one
     component: the same bump in the header pushed the row 4px past the
     375px viewport and cut the burger's tap target from 44 to 40px, and the
     burger is the only way into the navigation below 576px. */
  .ds-sticky-cta .ds-button--sm {
    font-size: var(--ds-text-body-sm);
  }
  .ds-site-header__actions {
    gap: var(--ds-space-1-5);
  }
  .ds-site-header__actions .ds-button--sm {
    padding-inline: 10px;
  }
  /* Purely decorative arrow (aria-hidden) on the header signup CTA. The
     fluid gap/padding above buys back most of the 361px minimum, but not
     all of it at 320px; dropping the ornament closes the rest without
     touching a label, a control or the brand. */
  .ds-site-header__actions .ds-button--primary > svg {
    display: none;
  }
}

.ds-wallet-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-1-5) var(--ds-space-3);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-blue);
  background: linear-gradient(
    135deg,
    var(--ds-surface-tint),
    var(--ds-surface)
  );
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-sm);
  text-decoration: none;
  transition: all var(--ds-dur-base) var(--ds-ease-out);
  position: relative;
}

.ds-wallet-badge:hover {
  background: var(--ds-gradient-brand);
  color: var(--ds-white);
  border-color: transparent;
  transform: translateY(-1px);
}

.ds-wallet-badge:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* Credit count inside the badge — tabular digits keep the header steady
   while the balance animates or changes width. */
.ds-wallet-badge__value {
  font-variant-numeric: tabular-nums;
}

.ds-wallet-badge--low {
  border-color: rgba(var(--ds-warn-bright-rgb), 0.3);
  color: var(--ds-warn);
}

.ds-wallet-badge--critical {
  border-color: var(--ds-danger);
  color: var(--ds-danger);
  animation: ds-wallet-pulse 1.4s ease-in-out infinite;
}

@keyframes ds-wallet-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(var(--ds-danger-rgb), 0);
  }
  50% {
    box-shadow: 0 0 0 4px rgba(var(--ds-danger-rgb), 0.15);
  }
}

.ds-avatar-menu {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-gradient-icon-tile);
  background-size: 200% 200%;
  background-position: 0% 50%;
  color: var(--ds-white);
  font-weight: var(--ds-fw-black);
  font-size: var(--ds-text-body-sm);
  letter-spacing: -0.01em;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 4px 12px rgba(var(--ds-blue-rgb), 0.25);
  transition:
    transform var(--ds-dur-base) var(--ds-ease-out),
    box-shadow var(--ds-dur-base) var(--ds-ease-out),
    background-position var(--ds-dur-slow) var(--ds-ease-out);
}

.ds-avatar-menu:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

a.ds-avatar-menu:hover,
.ds-avatar-menu:hover {
  color: var(--ds-white);
  transform: translateY(-1px) scale(1.06);
  background-position: 100% 50%;
  box-shadow:
    0 8px 20px rgba(var(--ds-blue-rgb), 0.35),
    0 0 0 4px rgba(var(--ds-blue-rgb), 0.12);
}

a.ds-avatar-menu::after {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: var(--ds-radius-full);
  border: 2px solid transparent;
  background: linear-gradient(
      135deg,
      rgba(var(--ds-blue-rgb), 0.35),
      rgba(var(--ds-purple-rgb), 0.35)
    )
    border-box;
  -webkit-mask:
    linear-gradient(var(--ds-white) 0 0) padding-box,
    linear-gradient(var(--ds-white) 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transform: scale(0.85);
  transition:
    opacity var(--ds-dur-base) var(--ds-ease-out),
    transform var(--ds-dur-base) var(--ds-ease-out);
  pointer-events: none;
}

a.ds-avatar-menu:hover::after {
  opacity: 1;
  transform: scale(1);
}

.ds-site-header__burger {
  display: none;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0;
  color: var(--ds-ink);
}

.ds-site-header__burger:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

@media (max-width: 991px) {
  .ds-site-header__burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

@media (max-width: 767px) {
  .ds-site-header__actions .ds-wallet-badge {
    padding: var(--ds-space-1-5) var(--ds-space-2);
  }
  .ds-site-header__actions .ds-wallet-badge__label {
    display: none;
  }
}

.ds-site-header--minimal {
  position: static;
  background: var(--ds-surface);
  border-bottom: 1px solid var(--ds-border-subtle);
}
.ds-site-header--minimal .ds-site-header__progress {
  display: none;
}

/* === Site Footer ===
   Marketing footer: atmosphere layer (conic gradient + subtle grid),
   5-column grid (Brand + Product + Resources + Legal + Contact),
   trust-signals row and extended legal strip. Tokens-aligned.
   Unified footer for marketing, app, auth, and error pages. */

.ds-site-footer {
  position: relative;
  background: var(--ds-surface-dark);
  color: rgba(var(--ds-white-rgb), 0.6);
  overflow: hidden;
  isolation: isolate;
}

/* Thin gradient accent at the top edge: visual transition from content into the dark footer. */
.ds-site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(var(--ds-blue-glow-rgb), 0.45) 20%,
    rgba(168, 85, 247, 0.6) 50%,
    rgba(var(--ds-red-rgb), 0.4) 80%,
    transparent 100%
  );
  z-index: 2;
  pointer-events: none;
}

.ds-site-footer__atmo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(
      60% 50% at 12% 0%,
      rgba(var(--ds-blue-glow-rgb), 0.2),
      transparent 60%
    ),
    radial-gradient(
      50% 60% at 92% 35%,
      rgba(168, 85, 247, 0.16),
      transparent 65%
    ),
    radial-gradient(
      40% 40% at 50% 100%,
      rgba(var(--ds-red-rgb), 0.1),
      transparent 70%
    ),
    linear-gradient(rgba(var(--ds-white-rgb), 0.035) 1px, transparent 1px),
    linear-gradient(
      90deg,
      rgba(var(--ds-white-rgb), 0.035) 1px,
      transparent 1px
    );
  background-size:
    auto,
    auto,
    auto,
    28px 28px,
    28px 28px;
  mask-image: linear-gradient(
    180deg,
    rgba(var(--ds-black-rgb), 0.9),
    rgba(var(--ds-black-rgb), 0.4) 70%,
    rgba(var(--ds-black-rgb), 0.15)
  );
  -webkit-mask-image: linear-gradient(
    180deg,
    rgba(var(--ds-black-rgb), 0.9),
    rgba(var(--ds-black-rgb), 0.4) 70%,
    rgba(var(--ds-black-rgb), 0.15)
  );
}

.ds-site-footer > * {
  position: relative;
  z-index: 1;
}

.ds-site-footer__main {
  padding: clamp(40px, 6vw, 72px) var(--ds-space-6) var(--ds-space-6);
  max-width: 1320px;
  margin: 0 auto;
}

.ds-site-footer__grid {
  display: grid;
  gap: var(--ds-space-8) var(--ds-space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 576px) {
  .ds-site-footer__grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 992px) {
  .ds-site-footer__grid {
    grid-template-columns: 1.9fr 1fr 1fr 1fr 1.4fr;
  }
}

/* ---- Brand column ---- */
.ds-site-footer__brand {
  max-width: 320px;
}

.ds-site-footer__wordmark-row {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  margin-bottom: var(--ds-space-3);
}

.ds-site-footer__brand-mark {
  width: 40px;
  height: 40px;
  border-radius: var(--ds-radius-sm);
  background: var(--ds-gradient-brand);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--ds-space-1-5);
  box-shadow:
    0 6px 20px rgba(var(--ds-blue-rgb), 0.45),
    inset 0 1px 0 rgba(var(--ds-white-rgb), 0.24);
  flex-shrink: 0;
}

.ds-site-footer__brand-mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  filter: brightness(0) invert(1);
}

.ds-site-footer__brand-wordmark {
  font-size: 22px;
  font-weight: var(--ds-fw-black);
  letter-spacing: var(--ds-tracking-tight);
  background: var(--ds-gradient-brand-on-dark);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  margin: 0;
  line-height: 1;
}

.ds-site-footer__brand p {
  font-size: var(--ds-text-body-sm);
  color: rgba(var(--ds-white-rgb), 0.6);
  margin: 0;
  line-height: var(--ds-lh-prose);
}

.ds-site-footer__brand-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
  margin-top: var(--ds-space-4);
}

.ds-footer-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  padding: var(--ds-space-1) var(--ds-space-2-5);
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-white-rgb), 0.05);
  border: 1px solid var(--ds-surface-dark-border);
  color: rgba(var(--ds-white-rgb), 0.8);
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-semi);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.ds-footer-chip i {
  color: var(--ds-lavender);
  font-size: var(--ds-text-eyebrow);
}

/* ---- Link columns ---- */
.ds-site-footer__col h4,
.ds-site-footer__col h5 {
  font-size: var(--ds-text-eyebrow);
  letter-spacing: var(--ds-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ds-lavender);
  font-weight: var(--ds-fw-black);
  margin: 0 0 var(--ds-space-3);
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
}

.ds-site-footer__col h4::before,
.ds-site-footer__col h5::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-lavender);
}

.ds-site-footer__col a {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  font-size: var(--ds-text-body-sm);
  color: rgba(var(--ds-white-rgb), 0.68);
  padding: var(--ds-space-1) 0;
  text-decoration: none;
  transition:
    color var(--ds-dur-fast) var(--ds-ease-out),
    transform var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-site-footer__col a i {
  font-size: var(--ds-text-caption);
  color: rgba(var(--ds-white-rgb), 0.42);
  transition: color var(--ds-dur-fast) var(--ds-ease-out);
  width: 14px;
  text-align: center;
  flex-shrink: 0;
}

.ds-site-footer__col a:hover {
  color: var(--ds-white);
  transform: translateX(2px);
}

.ds-site-footer__col a:hover i {
  color: var(--ds-lavender);
}

/* ---- Contact column ---- */
.ds-site-footer__col--contact .ds-site-footer__address {
  display: flex;
  gap: var(--ds-space-2);
  margin-top: var(--ds-space-3);
  padding-top: var(--ds-space-3);
  border-top: 1px solid rgba(var(--ds-white-rgb), 0.06);
  font-size: var(--ds-text-body-sm);
  color: rgba(var(--ds-white-rgb), 0.62);
  line-height: var(--ds-lh-prose);
}

.ds-site-footer__col--contact .ds-site-footer__address i {
  color: rgba(var(--ds-white-rgb), 0.42);
  font-size: var(--ds-text-body-sm);
  margin-top: var(--ds-space-0-5);
  flex-shrink: 0;
}

/* ---- Trust-Signal row ---- */
.ds-site-footer__signals {
  max-width: 1320px;
  margin: var(--ds-space-8) auto 0;
  padding: var(--ds-space-5) var(--ds-space-6) 0;
  border-top: 1px solid rgba(var(--ds-white-rgb), 0.08);
  display: grid;
  gap: var(--ds-space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .ds-site-footer__signals {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 992px) {
  .ds-site-footer__signals {
    grid-template-columns: repeat(4, 1fr);
  }
}

.ds-site-footer__signal {
  display: flex;
  align-items: flex-start;
  gap: var(--ds-space-3);
  color: rgba(var(--ds-white-rgb), 0.72);
}

.ds-site-footer__signal-icon {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: var(--ds-radius-sm);
  background:
    radial-gradient(
      circle at 30% 30%,
      rgba(168, 85, 247, 0.22),
      transparent 70%
    ),
    rgba(var(--ds-blue-glow-rgb), 0.1);
  border: 1px solid rgba(var(--ds-blue-glow-rgb), 0.22);
  color: var(--ds-lavender-light);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--ds-text-body);
  box-shadow: inset 0 1px 0 rgba(var(--ds-white-rgb), 0.08);
  transition:
    transform var(--ds-dur-fast) var(--ds-ease-out),
    border-color var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-site-footer__signal:hover .ds-site-footer__signal-icon {
  transform: translateY(-1px);
  border-color: rgba(168, 85, 247, 0.38);
}

.ds-site-footer__signal strong {
  display: block;
  color: var(--ds-white);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-tight);
  margin-bottom: var(--ds-space-0-5);
}

.ds-site-footer__signal small {
  display: block;
  font-size: var(--ds-text-eyebrow);
  color: rgba(var(--ds-white-rgb), 0.55);
  line-height: 1.4;
}

/* ---- Legal strip ---- */
.ds-site-footer__legal {
  max-width: 1320px;
  margin: var(--ds-space-6) auto 0;
  padding: var(--ds-space-4) var(--ds-space-6) var(--ds-space-5);
  border-top: 1px solid rgba(var(--ds-white-rgb), 0.08);
  font-size: var(--ds-text-eyebrow);
  color: rgba(
    var(--ds-white-rgb),
    0.72
  ); /* WCAG AA compliant on --ds-surface-dark */
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--ds-space-4);
  flex-wrap: wrap;
}

.ds-site-footer__legal-entity {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  flex-wrap: wrap;
}

.ds-site-footer__legal-entity .ds-site-footer__sep {
  color: rgba(var(--ds-white-rgb), 0.22);
}

.ds-site-footer__legal-actions {
  display: flex;
  align-items: center;
  gap: var(--ds-space-5);
  flex-wrap: wrap;
}

.ds-site-footer__legal-links {
  display: flex;
  gap: var(--ds-space-4);
  flex-wrap: wrap;
}

.ds-site-footer__legal-links a,
.ds-site-footer__legal-links .ds-footer-link-button {
  color: rgba(var(--ds-white-rgb), 0.72);
  text-decoration: none;
  transition: color var(--ds-dur-fast) var(--ds-ease-out);
  /* WCAG 2.2 SC 2.5.8: the legal links are the row with the smallest hit
     area on the site (17-18 px measured) and sit 16 px apart, so neither the
     size nor the spacing exception applied. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.ds-site-footer__legal-links a:hover,
.ds-site-footer__legal-links .ds-footer-link-button:hover {
  color: var(--ds-white);
}

.ds-site-footer__legal-links a:focus-visible,
.ds-site-footer__legal-links .ds-footer-link-button:focus-visible,
.ds-site-footer__to-top:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* Footer consent re-open control — a <button> (it triggers JS, not a
   navigation) visually aligned with the sibling footer links. */
.ds-footer-link-button {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
}

.ds-site-footer__legal-location {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
}

.ds-site-footer__legal-location i {
  color: var(--ds-lavender);
}

/* Austria flag ribbon (red-white-red) — subtle origin accent in the legal strip. */
.ds-site-footer__flag {
  display: inline-block;
  width: 14px;
  height: 10px;
  /* Deliberately below the --ds-radius scale: at 14x10px the smallest scale
     step (6px) clamps to 5px and turns the flag ribbon into a pill. A
     decorative element this small needs a sub-scale corner. */
  border-radius: 2px;
  background: linear-gradient(
    180deg,
    var(--ds-red) 0 33%,
    var(--ds-white) 33% 66%,
    var(--ds-red) 66% 100%
  );
  box-shadow: 0 0 0 1px rgba(var(--ds-white-rgb), 0.2);
  flex-shrink: 0;
  vertical-align: middle;
}

/* Back-to-top anchor: subtle icon button at the top-right of the legal strip. */
.ds-site-footer__to-top {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  padding: var(--ds-space-1-5) var(--ds-space-3);
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-white-rgb), 0.04);
  border: 1px solid var(--ds-surface-dark-border);
  color: rgba(var(--ds-white-rgb), 0.72);
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-semi);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  text-decoration: none;
  transition:
    background var(--ds-dur-fast) var(--ds-ease-out),
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-site-footer__to-top:hover {
  background: rgba(var(--ds-blue-glow-rgb), 0.14);
  border-color: rgba(var(--ds-blue-glow-rgb), 0.35);
  color: var(--ds-white);
}

.ds-site-footer__to-top i {
  font-size: var(--ds-text-caption);
  color: var(--ds-lavender);
}

.ds-site-footer__to-top:hover i {
  color: var(--ds-white);
}

.ds-site-footer--minimal {
  background: var(--ds-surface);
  color: var(--ds-ink-mute);
  border-top: 1px solid var(--ds-border-subtle);
  padding: var(--ds-space-4) var(--ds-space-6);
}

.ds-app-footer__inner {
  max-width: 1320px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-4);
  flex-wrap: wrap;
}

.ds-app-footer__copyright {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
}

.ds-app-footer__links {
  display: flex;
  gap: var(--ds-space-4);
  flex-wrap: wrap;
}

.ds-app-footer__links a,
.ds-app-footer__links .ds-footer-link-button {
  color: var(--ds-ink-soft);
  text-decoration: none;
  font-size: var(--ds-text-caption);
  transition: color var(--ds-dur-fast) var(--ds-ease-out);
  /* Same SC 2.5.8 floor as the marketing footer's legal row. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.ds-app-footer__links a:hover,
.ds-app-footer__links a:focus-visible,
.ds-app-footer__links .ds-footer-link-button:hover,
.ds-app-footer__links .ds-footer-link-button:focus-visible {
  color: var(--ds-blue);
}

@media (max-width: 575px) {
  .ds-app-footer__inner {
    justify-content: center;
    text-align: center;
  }
  /* Center the wrapping link rows too, so a wrapped link ("Support") does
       not orphan left-flush under the centered copyright line. */
  .ds-app-footer__links {
    justify-content: center;
  }
}

/* === Consent banner (self-hosted DSGVO cookie consent) === */

.ds-consent {
  position: fixed;
  bottom: var(--ds-space-4);
  left: var(--ds-space-4);
  right: var(--ds-space-4);
  max-width: 520px;
  margin: 0 auto;
  /* Below the modal layers: an open confirm dialog or filter sheet must
       win against the cookie banner. */
  z-index: var(--ds-z-consent);
  outline: none;
}

.ds-consent[hidden] {
  display: none;
}

.ds-consent__card {
  padding: var(--ds-space-4) var(--ds-space-5);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-lg);
}

.ds-consent__title {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  margin: 0 0 var(--ds-space-2);
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
}

.ds-consent__title .bi {
  color: var(--ds-blue);
}

.ds-consent__text {
  margin: 0 0 var(--ds-space-4);
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-prose);
  color: var(--ds-ink-soft);
}

.ds-consent__text a {
  color: var(--ds-blue);
}

.ds-consent__actions {
  display: flex;
  gap: var(--ds-space-3);
  flex-wrap: wrap;
}

@media (max-width: 575px) {
  .ds-consent__actions {
    flex-direction: column;
  }
  .ds-consent__actions .ds-button {
    width: 100%;
    justify-content: center;
  }
}

/* ============================================================================
 * DS CONTRAST FIXES — Post-Migration Polish
 * Context-overrides for cases where class-inheritance led to contrast bugs.
 * ========================================================================== */

/* Compare-Table: cells inherit color from their dark-section parent.
   Force the table itself to be a light-background island with dark ink. */
.ds-compare-table td span,
.ds-compare-table td small {
  color: inherit;
}
.ds-compare-table .ds-compare-mid,
.ds-compare-table .ds-compare-yes,
.ds-compare-table .ds-compare-no {
  color: var(--ds-ink-soft);
}
/* Favorite-column accents — compound td/th selectors outrank the generic
   cell color rules above, so no !important is needed. */
.ds-compare-table td.ds-compare-table__col--highlight,
.ds-compare-table th.ds-compare-table__col--highlight {
  /* Brand-blue text for the Favorite column (bold, vivid, but not loud). */
  color: var(--ds-blue);
  font-weight: var(--ds-fw-black);
}
.ds-compare-table td.ds-compare-table__col--highlight .ds-compare-yes {
  color: var(--ds-success);
  font-weight: var(--ds-fw-black);
}
.ds-compare-table td.ds-compare-table__col--highlight .ds-compare-mid,
.ds-compare-table td.ds-compare-table__col--highlight .ds-compare-no {
  color: var(--ds-blue);
}

/* Section titles that live directly in a dark section but lack .ds-section__title.
   Specificity 0,0,2,0 so it wins over .ds-layout-shell (0,0,1,0) body-color inheritance. */
.ds-section--dark h2,
.ds-section--dark-pattern h2,
.ds-section--dark h3,
.ds-section--dark-pattern h3,
.ds-section--dark h4,
.ds-section--dark-pattern h4 {
  color: var(--ds-white);
}

.ds-section--dark p,
.ds-section--dark-pattern p {
  color: rgba(var(--ds-white-rgb), 0.78);
}

/* Override back to dark ink INSIDE light cards/panels/tables — higher specificity so
   the card-islands-on-dark-section cases get dark text again. Use compound .a.b or
   triple-selector to win over the above h2/h3 dark-section rule. */
.ds-section--dark .ds-card h2,
.ds-section--dark .ds-card h3,
.ds-section--dark .ds-card h4,
.ds-section--dark .ds-card h5,
.ds-section--dark .ds-card h6,
.ds-section--dark-pattern .ds-card h2,
.ds-section--dark-pattern .ds-card h3,
.ds-section--dark-pattern .ds-card h4,
.ds-section--dark-pattern .ds-card h5,
.ds-section--dark-pattern .ds-card h6,
.ds-section--dark .ds-panel h2,
.ds-section--dark .ds-panel h3,
.ds-section--dark .ds-panel h4,
.ds-section--dark .ds-panel h5,
.ds-section--dark .ds-panel h6,
.ds-section--dark .ds-compare-table h2,
.ds-section--dark .ds-compare-table h3,
.ds-section--dark .ds-compare-table h4 {
  color: var(--ds-ink);
}

.ds-section--dark .ds-card p,
.ds-section--dark-pattern .ds-card p,
.ds-section--dark .ds-panel p,
.ds-section--dark .ds-compare-table p {
  color: var(--ds-ink-soft);
}

/* Links in gradient/dark hero-like sections: force white, underline on hover */
.ds-cta-band a:not(.ds-button):not(.btn):not([class*="ds-op-cta"]),
.ds-hero--dramatic a:not(.ds-button):not(.btn):not([class*="ds-op-cta"]),
.ds-section--dark
  a:not(.ds-button):not(.btn):not([class*="ds-op-cta"]):not(
    .ds-site-footer__col a
  ):not(.ds-site-footer__brand),
.ds-section--dark-pattern
  a:not(.ds-button):not(.btn):not([class*="ds-op-cta"]) {
  color: var(--ds-white);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ds-button--secondary inside dark/gradient context: use on-dark variant styles automatically */
.ds-section--dark .ds-button--secondary:not(.ds-button--secondary--on-dark),
.ds-section--dark-pattern
  .ds-button--secondary:not(.ds-button--secondary--on-dark),
.ds-hero--dramatic .ds-button--secondary:not(.ds-button--secondary--on-dark),
.ds-cta-band .ds-button--secondary:not(.ds-button--secondary--on-dark) {
  color: var(--ds-white);
  border-color: rgba(var(--ds-white-rgb), 0.4);
}
.ds-section--dark
  .ds-button--secondary:not(.ds-button--secondary--on-dark):hover,
.ds-section--dark-pattern
  .ds-button--secondary:not(.ds-button--secondary--on-dark):hover,
.ds-hero--dramatic
  .ds-button--secondary:not(.ds-button--secondary--on-dark):hover,
.ds-cta-band .ds-button--secondary:not(.ds-button--secondary--on-dark):hover {
  background: rgba(var(--ds-white-rgb), 0.12);
  border-color: rgba(var(--ds-white-rgb), 0.6);
  color: var(--ds-white);
}

/* Ensure .ds-hero--dramatic wins over accidentally-stacked .ds-section--atmo/.ds-section--atmo classes */
.ds-hero.ds-hero--dramatic,
section.ds-hero--dramatic {
  background: linear-gradient(
    135deg,
    var(--ds-surface-dark) 0%,
    var(--ds-surface-dark-2) 50%,
    var(--ds-surface-dark-violet) 100%
  );
  color: var(--ds-white);
}
.ds-hero.ds-hero--dramatic .ds-hero__title {
  color: var(--ds-white);
}
.ds-hero.ds-hero--dramatic .ds-hero__lead {
  color: rgba(var(--ds-white-rgb), 0.78);
}

/* The hero mini-stats carry white-transparent text that is legible only on the
   dark hero. Inside a light standard hero, force darker ink. (Defensive.) */
.ds-hero--standard .ds-hero-minstats span {
  color: var(--ds-ink-soft);
}

/* ============================================================================
 * LEGACY APP.CSS — merged into leadsuche.css as part of Phase 2 cleanup.
 * Originally sourced from static/css/app.css (3984 lines).
 * Contains: app-shell layout utilities, stat-card, app-card, lead-card,
 *   app-prem-* decoratives, home-* LP sub-components, etc.
 * Coexists with .ds-* namespace; can be incrementally removed in future polish.
 * ========================================================================== */

/* ============================================================================
 * LeadSuche — App CSS · Components for authenticated areas
 * Wallet Badge · Filter Bar · Lead Cards (blurred + unlocked) ·
 * Unlock Bar · Stat Cards · Side Panel Layouts
 * ============================================================================ */

/* === App-Layout-Container ===
   Legacy `min-height: calc(100vh - 64px)` removed: it was a holdover from an
   old fixed top-bar that subtracted itself from the body. The current header
   participates in the body's flex column, so it does not need to be
   subtracted. The sticky-footer pattern lives on `.ds-layout-shell`
   (`min-height: 100vh; display: flex; flex-direction: column`). */
.app-shell {
  background: var(--ds-surface-muted);
}
.app-container {
  width: 100%;
  max-width: 1320px;
  min-width: 0;
  margin: 0 auto;
  /* Symmetric 24px top/bottom; zero horizontal so content reaches the
       container edge on wide screens. On viewports narrower than the
       1320px max-width, a 12px safety padding kicks in (see media query
       below) to absorb the negative margins of Bootstrap .row elements. */
  padding: var(--ds-space-6) 0;
}

/* Content-driven exception: matches the 1320px .app-container cap — below it
   the side gutters collapse to half a Bootstrap gutter. Expressed in rem, not
   as the literal 12px it resolves to at the default root size: the gutter it
   compensates is itself rem-based (--bs-gutter-x: 1.5rem), so a reader who
   raises the browser's base font grew the negative margin while a px padding
   stayed put — 6px of every app page was clipped at a 24px root. */
@media (max-width: 1320px) {
  .app-container {
    padding-inline: 0.75rem;
  }
}

/* On app-shell pages the sidebar offsets the content area to the right, so
   the container no longer sits centered with viewport-side margin. Force
   the 12px Bootstrap-gutter-compensation padding on every breakpoint to
   prevent row negative margins from triggering horizontal scroll. */
body.ds-layout-shell--app .app-container {
  padding-inline: 0.75rem;
}

/* ============================================================================
 * Lead-Search — Unlock-Bar (Top-N input) + Table/Row-list layout
 * ========================================================================== */

.ds-unlock-bar {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(1rem, 2.5vw, 2rem);
  align-items: center;
  padding: clamp(1.25rem, 2.2vw, 1.5rem) clamp(1.5rem, 3vw, 2rem);
  margin-bottom: var(--ds-space-6);
  background: linear-gradient(
    135deg,
    var(--ds-white) 0%,
    var(--ds-surface-tint) 100%
  );
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-md);
  box-shadow:
    0 1px 2px rgba(var(--ds-blue-rgb), 0.04),
    0 8px 24px -8px rgba(var(--ds-blue-rgb), 0.12);
}

/* Text column of the unlock bar (title + lead) — must be allowed to
   shrink inside the bar's grid so the control column never clips. */
.ds-unlock-bar__copy {
  min-width: 0;
}

.ds-unlock-bar__title {
  font-size: var(--ds-text-lg);
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  margin: 0 0 var(--ds-space-1-5);
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
}
.ds-unlock-bar__title .bi {
  color: var(--ds-blue);
}
.ds-unlock-bar__lead {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-mute);
  margin: 0;
  line-height: var(--ds-lh-base);
}

.ds-unlock-bar__control {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-1);
  min-width: 340px;
}
.ds-unlock-bar__label {
  font-size: 0.72rem;
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink-mute);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.ds-unlock-bar__input-row {
  display: flex;
  /* Defensive wrap: between 576px and 767px the row may still be tighter
       than input + CTA; wrapping beats clipping the primary conversion CTA. */
  flex-wrap: wrap;
  gap: var(--ds-space-2-5);
  align-items: stretch;
}

.ds-input-wrap {
  position: relative;
  flex: 0 0 auto;
  min-width: 160px;
}

@media (max-width: 767px) {
  .ds-unlock-bar {
    grid-template-columns: 1fr;
  }
  /* The 340px control floor is a desktop nicety — on narrow viewports it
       forces the input row past the card edge and clips the submit CTA. */
  .ds-unlock-bar__control {
    min-width: 0;
  }
}

@media (max-width: 575px) {
  /* Stack amount input and submit CTA; the credit hint inside the button
       stays fully visible because the button spans the card width. */
  .ds-unlock-bar__input-row {
    flex-direction: column;
    align-items: stretch;
  }
  .ds-input-wrap {
    min-width: 0;
  }
  .ds-unlock-bar__submit {
    width: 100%;
    justify-content: center;
  }
}

.ds-unlock-bar__input {
  width: 100%;
  padding-right: var(--ds-space-20);
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  height: 44px;
}
.ds-input-suffix {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-semi);
  pointer-events: none;
  background: var(--ds-white);
  padding: var(--ds-space-0-5) 0;
}

.ds-unlock-bar__submit {
  flex-shrink: 0;
  height: 44px;
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
}
.ds-unlock-bar__credit-hint {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-medium);
  opacity: 0.82;
  padding-left: var(--ds-space-1-5);
  border-left: 1px solid rgba(var(--ds-white-rgb), 0.3);
  margin-left: var(--ds-space-0-5);
}

.ds-perpage-form {
  display: inline-flex;
  margin: 0;
}
.ds-perpage-form select {
  width: auto;
  min-width: 70px;
}

/* ============================================================================
 * Lead-Table — dense row-list layout (50-100 records per view)
 * ========================================================================== */

.ds-lead-table-wrap {
  border-radius: var(--ds-radius-md);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  border: 1px solid var(--ds-border-subtle);
  box-shadow:
    0 1px 2px rgba(var(--ds-blue-rgb), 0.04),
    0 4px 16px -4px rgba(var(--ds-blue-rgb), 0.06);
}

.ds-lead-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--ds-text-body-sm);
}

.ds-lead-table thead {
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.04),
    rgba(var(--ds-purple-rgb), 0.03)
  );
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.1);
}

.ds-lead-table th {
  padding: var(--ds-space-3);
  font-size: 0.72rem;
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink-mute);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: left;
  white-space: nowrap;
}

.ds-lead-table td {
  padding: var(--ds-space-3);
  border-bottom: 1px solid rgba(var(--ds-blue-rgb), 0.04);
  color: var(--ds-ink);
  vertical-align: middle;
}

.ds-lead-table tbody tr {
  transition: background var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-lead-table tbody tr:hover {
  background: rgba(var(--ds-blue-rgb), 0.02);
}
.ds-lead-table tbody tr:last-child td {
  border-bottom: 0;
}

.ds-lead-table__company {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2-5);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
}
.ds-lead-table__company .bi {
  font-size: 1.05rem;
}

.ds-lead-table__muted {
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-medium);
}

.ds-lead-table__icons {
  display: inline-flex;
  gap: var(--ds-space-2-5);
  align-items: center;
  font-size: var(--ds-text-body);
}

.ds-score-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: var(--ds-radius-full);
  background: rgba(var(--ds-blue-rgb), 0.08);
  color: var(--ds-blue);
  font-weight: var(--ds-fw-bold);
  font-size: 0.82rem;
}

.ds-lead-table .ds-lead-contact {
  filter: blur(4px);
  user-select: none;
}

/* Highlight snippet beneath the company name; clamped to avoid
   the cell growing too wide on large screens. */
.ds-lead-table__snippet {
  max-width: 32ch;
}

/* Row-level lock state hooks — visual differentiation is carried by
   child icon and ds-lead-contact blur, but these modifiers are kept
   as semantic handles for future token-driven styling or JS queries. */
.ds-lead-table tbody tr.is-locked td:first-child {
  opacity: 0.85;
}
.ds-lead-table tbody tr.is-unlocked td:first-child {
  opacity: 1;
}

/* Long labels inside table badges (industry names) must not dictate the
   table's intrinsic width — clamp with an ellipsis; the full value stays
   reachable via the cell's title attribute. */
.ds-lead-table .ds-lead-table__cell--industry .ds-badge {
  display: inline-block;
  max-width: 20ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Hide less-important columns on narrower viewports. The 1320px boundary
   is content-driven: below it the 240px sidebar plus the lead table's
   intrinsic width no longer fit, so the lowest-priority columns yield
   before the wrap starts clipping score and action columns. */
@media (max-width: 1320px) {
  .ds-lead-table .hide-lg {
    display: none;
  }
}
@media (max-width: 991px) {
  .ds-lead-table .hide-md {
    display: none;
  }
}
@media (max-width: 767px) {
  .ds-lead-table-wrap {
    overflow-x: auto;
  }
  .ds-lead-table {
    min-width: 700px;
  }
}

/* ============================================================================
 * Records View (formerly "Unlocked") — top-right export toolbar with
 * filter options (scope + format) above the records table.
 * ========================================================================== */

.ds-records-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: var(--ds-space-3-5) var(--ds-space-4-5);
  margin-bottom: 0;
  background: linear-gradient(
    135deg,
    var(--ds-white) 0%,
    var(--ds-surface-tint) 100%
  );
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-bottom: 0;
  border-radius: var(--ds-radius-md) var(--ds-radius-md) 0 0;
}

.ds-records-toolbar__count {
  display: flex;
  align-items: baseline;
  gap: var(--ds-space-2);
}
.ds-records-toolbar__count-value {
  font-family: var(--ds-font-display);
  font-size: 1.25rem;
  font-weight: var(--ds-fw-black);
  color: var(--ds-blue);
  letter-spacing: var(--ds-tracking-tight);
}
.ds-records-toolbar__count-label {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-semi);
}

.ds-records-toolbar__actions {
  display: flex;
  align-items: flex-end;
  gap: var(--ds-space-3);
  flex-wrap: wrap;
}

/* The Auswahl/Format selects are 44px tall; the Export button has no field
   label above it, so without a matching height it bottom-aligns as a shorter
   35px box that sits visibly lower. Match the control height so all three line
   up on the same baseline. */
.ds-records-toolbar__actions > button {
  height: 44px;
}

.ds-records-toolbar__field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0;
}
.ds-records-toolbar__field-label {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}
.ds-records-toolbar__field select {
  min-width: 150px;
}

/* When the toolbar is used, table-wrap stacks on top without top-radius. */
.ds-records-toolbar + .ds-lead-table-wrap {
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* ============================================================================
 * Dashboard Plan-Status-Card — pricy typography, 4-column grid (icon · meta ·
 * price · credits · action), collapses to 2-column on narrow viewports.
 * ========================================================================== */
/* Block root — the card chrome comes from the surrounding ds-card; the
   root only needs to isolate its layout context. */
.ds-plan-status {
  min-width: 0;
}

.ds-plan-status__body {
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  padding: clamp(1.25rem, 2.5vw, 1.75rem) clamp(1.5rem, 3vw, 2rem);
}

.ds-plan-status__icon {
  width: 56px;
  height: 56px;
  border-radius: var(--ds-radius-md);
  background: var(--ds-gradient-icon-tile);
  color: var(--ds-white);
  font-size: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--ds-shadow-icon-tile-lg);
  flex-shrink: 0;
}

.ds-plan-status__meta {
  min-width: 0;
}

.ds-plan-status__eyebrow {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
  line-height: 1;
  margin-bottom: var(--ds-space-1-5);
}

.ds-plan-status__name {
  font-family: var(--ds-font-display);
  font-size: clamp(1.5rem, 2.2vw, 1.875rem);
  font-weight: var(--ds-fw-black);
  line-height: var(--ds-lh-tight);
  letter-spacing: var(--ds-tracking-tight);
  background: var(--ds-gradient-icon-tile);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.ds-plan-status__renewal {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  margin-top: var(--ds-space-1);
}

.ds-plan-status__price,
.ds-plan-status__credits {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ds-space-0-5);
  padding-left: clamp(1rem, 2vw, 1.5rem);
  border-left: 1px solid rgba(var(--ds-blue-rgb), 0.1);
}

.ds-plan-status__price-value,
.ds-plan-status__credits-value {
  font-family: var(--ds-font-display);
  font-size: clamp(1.5rem, 2vw, 1.75rem);
  font-weight: var(--ds-fw-black);
  line-height: 1;
  color: var(--ds-ink);
  letter-spacing: var(--ds-tracking-tight);
}

.ds-plan-status__price-unit,
.ds-plan-status__credits-unit {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink-mute);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ds-plan-status__action {
  margin-left: clamp(0.5rem, 1vw, 1rem);
}

@media (max-width: 991px) {
  .ds-plan-status__body {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "icon meta"
      "price credits"
      "action action";
    row-gap: 1rem;
  }
  .ds-plan-status__icon {
    grid-area: icon;
  }
  .ds-plan-status__meta {
    grid-area: meta;
  }
  .ds-plan-status__price {
    grid-area: price;
    padding-left: 0;
    border-left: 0;
  }
  .ds-plan-status__credits {
    grid-area: credits;
    padding-left: 1rem;
  }
  .ds-plan-status__action {
    grid-area: action;
    margin-left: 0;
  }
  .ds-plan-status__action .ds-button {
    width: 100%;
  }
}

/* ============================================================================
 * App-Hero as a premium card (Dashboard, Search, Billing, Team, Settings, …)
 * White→blue-pink gradient, blue-tinted border, 20px radius, animated
 * 3px top-bar, layered shadow. The hero aligns flush with Bootstrap-row
 * content (rows have a -12px gutter pull, so we match with negative margin).
 * ========================================================================== */

body.ds-layout-shell--app .app-container > .ds-hero:first-child {
  margin-top: 0;
  margin-left: -12px;
  margin-right: -12px;
  margin-bottom: var(--ds-space-6);
  width: auto;
  padding: clamp(1.5rem, 2.8vw, 2.25rem) clamp(1.5rem, 3vw, 2.5rem);

  background: linear-gradient(
    135deg,
    var(--ds-white) 0%,
    var(--ds-surface-tint) 55%,
    #fff4f3 100%
  );
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-lg);
  box-shadow:
    0 2px 4px rgba(var(--ds-blue-rgb), 0.04),
    0 20px 48px -20px rgba(var(--ds-blue-rgb), 0.15);
  position: relative;
  overflow: hidden;
}

body.ds-layout-shell--app .app-container > .ds-hero:first-child::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--ds-blue) 0%,
    var(--ds-purple) 50%,
    var(--ds-red) 100%
  );
  background-size: 200% 100%;
  animation: dsAppHeroBar 5s ease-in-out infinite;
  z-index: 1;
}

@keyframes dsAppHeroBar {
  0%,
  100% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
}

body.ds-layout-shell--app .app-container > .ds-hero:first-child .ds-hero__copy,
body.ds-layout-shell--app
  .app-container
  > .ds-hero:first-child
  .ds-hero__content {
  max-width: none;
  margin: 0;
  /* Prevent children (eyebrow pill, button row) from stretching to the full
       flex-column width — we want each child to be as wide as its own content. */
  align-items: flex-start;
  gap: var(--ds-space-3);
}

/* Dashboard + other pages that opt into a right-side stat widget next to
   the hero copy. The grid collapses on narrower viewports. */
body.ds-layout-shell--app .app-container > .ds-hero--with-stat {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
}

@media (max-width: 991px) {
  body.ds-layout-shell--app .app-container > .ds-hero--with-stat {
    grid-template-columns: 1fr;
    gap: var(--ds-space-4);
  }
}

@media (max-width: 575px) {
  body.ds-layout-shell--app .app-container > .ds-hero--with-stat {
    gap: var(--ds-space-3);
  }
}

/* Compact credit-stat widget on the right side of the dashboard hero. */
.ds-hero-stat {
  min-width: 220px;
  padding: var(--ds-space-5) var(--ds-space-6);
  background: var(--ds-white);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-md);
  box-shadow:
    0 1px 2px rgba(var(--ds-blue-rgb), 0.04),
    0 10px 24px rgba(var(--ds-blue-rgb), 0.08);
  text-align: center;
}

.ds-hero-stat__icon {
  width: 44px;
  height: 44px;
  border-radius: var(--ds-radius-sm);
  background: var(--ds-gradient-icon-tile);
  color: var(--ds-white);
  font-size: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--ds-space-2-5);
  box-shadow: var(--ds-shadow-icon-tile-lg);
}

.ds-hero-stat__value {
  font-family: var(--ds-font-display);
  font-size: clamp(2rem, 3vw, 2.75rem);
  font-weight: var(--ds-fw-black);
  line-height: 1;
  background: var(--ds-gradient-icon-tile);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  margin-bottom: var(--ds-space-1-5);
  letter-spacing: -0.03em;
}

.ds-hero-stat__label {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink-mute);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  line-height: 1.2;
}

/* ============================================================================
 * Filter-Bar (Search) — C6 horizontal filter layer above the results
 * Row 1: query + live count + sort + apply/reset. Row 2: six group buttons
 * with anchored popover panels. Row 3: applied-filter chips. Below 768px the
 * group container becomes a full-screen sheet (accordion groups + sticky
 * apply), toggled via body.ds-filter-sheet-open by filter.js.
 * ========================================================================== */

/* Results column below the filter bar — a shrinkable layout context for
   the table wrap; spacing comes from the bar's own margins. */
.ds-search-results {
  min-width: 0;
}

.ds-filter-bar {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-4);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-sm);
  padding: var(--ds-space-4) var(--ds-space-5);
  margin-top: var(--ds-space-5);
  margin-bottom: var(--ds-space-5);
}

.ds-filter-bar__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-3);
}

.ds-filter-bar__query {
  position: relative;
  flex: 1 1 240px;
  min-width: 0;
}

.ds-filter-bar__query > .bi {
  position: absolute;
  left: var(--ds-space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--ds-ink-mute);
  pointer-events: none;
}

.ds-filter-bar__query-input {
  padding-left: var(--ds-space-10);
}

.ds-filter-bar__count {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-1);
}

.ds-filter-count {
  font-family: var(--ds-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--ds-text-body);
  line-height: var(--ds-lh-tight);
  color: var(--ds-ink);
  white-space: nowrap;
}

.ds-filter-count strong {
  color: var(--ds-blue);
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-lg);
}

.ds-filter-count__balance {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
  white-space: nowrap;
}

.ds-filter-bar__sort {
  width: auto;
}

/* The mobile toggle and the sheet chrome only exist below 768px. */
.ds-filter-bar__mobile-toggle,
.ds-filter-bar__sheet-head,
.ds-filter-bar__sheet-foot {
  display: none;
}

/* Row 2 — group buttons with anchored popover panels. */
.ds-filter-bar__groups {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
}

.ds-filter-group {
  position: relative;
}

.ds-filter-group__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-2) var(--ds-space-4);
  font-family: inherit;
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-full);
  cursor: pointer;
  transition:
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    background-color var(--ds-dur-fast) var(--ds-ease-out),
    box-shadow var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-filter-group__toggle:hover {
  border-color: var(--ds-blue);
}

.ds-filter-group__toggle:focus-visible {
  outline: none;
  border-color: var(--ds-blue);
  box-shadow: var(--ds-shadow-focus);
}

.ds-filter-group.is-open > .ds-filter-group__toggle {
  border-color: var(--ds-blue);
  background: var(--ds-info-tint);
  color: var(--ds-blue);
}

.ds-filter-group__toggle .bi-chevron-down {
  font-size: var(--ds-text-caption);
  transition: transform var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-filter-group.is-open .bi-chevron-down {
  transform: rotate(180deg);
}

.ds-filter-group__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 var(--ds-space-1);
  border-radius: var(--ds-radius-full);
  background: var(--ds-blue);
  color: var(--ds-white);
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-bold);
  line-height: 1;
}

.ds-filter-group__panel {
  position: absolute;
  top: calc(100% + var(--ds-space-2));
  left: 0;
  z-index: var(--ds-z-dropdown);
  width: min(320px, calc(100vw - var(--ds-space-6)));
  /* filter.js sets --ls-panel-shift on open when the panel would otherwise
       reach past a viewport edge; 0 is the no-JS default. */
  margin-left: var(--ls-panel-shift, 0px);
  /* filter.js sets --ls-panel-max to the viewport remainder on open so
       the panel never extends below the fold; 70vh is the no-JS fallback. */
  max-height: var(--ls-panel-max, 70vh);
  overflow-y: auto;
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  box-shadow: var(--ds-shadow-lg);
  /* No bottom padding — the sticky foot supplies it, so "Übernehmen"
       stays visible while the panel body scrolls. */
  padding: var(--ds-space-5) var(--ds-space-5) 0;
}

.ds-filter-group__panel--wide {
  width: min(640px, calc(100vw - var(--ds-space-12)));
}

/* Right-anchored variant keeps the last groups' panels inside the viewport.
   The shift then has to move the other way, so it applies as a right margin
   — a left margin on a right-anchored box pushes nothing. */
.ds-filter-group__panel--end {
  left: auto;
  right: 0;
  margin-left: 0;
  margin-right: calc(-1 * var(--ls-panel-shift, 0px));
}

.ds-filter-group__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ds-space-5);
}

.ds-filter-group__foot {
  /* Pinned to the scrollport bottom of tall panels so the apply action
       never sits below the panel fold. */
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: flex-end;
  margin-top: var(--ds-space-4);
  padding-block: var(--ds-space-3) var(--ds-space-4);
  background: var(--ds-surface);
  border-top: 1px solid var(--ds-border-subtle);
}

.ds-filter-fieldset {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  min-width: 0;
  margin: 0 0 var(--ds-space-4);
  padding: 0;
  border: 0;
}

.ds-filter-group__grid .ds-filter-fieldset {
  margin-bottom: 0;
}

.ds-filter-fieldset__legend {
  font-size: var(--ds-text-caption);
  text-transform: uppercase;
  letter-spacing: var(--ds-tracking-eyebrow);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink-soft);
  padding: 0;
  margin-bottom: var(--ds-space-1);
}

.ds-filter-fieldset__hint {
  text-transform: none;
  letter-spacing: var(--ds-tracking-base);
  font-weight: var(--ds-fw-medium);
  color: var(--ds-ink-mute);
}

/* Long data-driven option lists (Branche, CMS, …) scroll after ~5 rows so
   one category can never push the panel beyond the viewport. */
.ds-filter-options {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  max-height: 190px;
  overflow-y: auto;
  padding-right: var(--ds-space-1);
}

.ds-filter-range {
  display: flex;
  gap: var(--ds-space-2);
}

.ds-filter-note {
  margin: 0 0 var(--ds-space-3);
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
}

/* Row 3 — applied filters as removable chips; clicking re-submits the GET
   state without the removed value (server-rendered remove links). */
.ds-filter-bar__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
}

/* Shown by filter.js while the live count no longer matches the rendered
   table. [hidden] must win over the .ds-alert display, hence the guard. */
.ds-filter-bar__stale {
  margin: var(--ds-space-3) 0 0;
}

.ds-filter-bar__stale[hidden] {
  display: none;
}

.ds-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  padding: var(--ds-space-1) var(--ds-space-3);
  border-radius: var(--ds-radius-full);
  background: var(--ds-info-tint);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.18);
  color: var(--ds-blue);
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  text-decoration: none;
  transition:
    background-color var(--ds-dur-fast) var(--ds-ease-out),
    border-color var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-filter-chip:hover {
  background: rgba(var(--ds-blue-rgb), 0.14);
  border-color: rgba(var(--ds-blue-rgb), 0.3);
  color: var(--ds-blue);
}
.ds-filter-chip:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

/* Results toolbar above the table — per-page select only; count and sort
   live in the filter bar. */
.ds-results-meta {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--ds-space-2);
  margin-bottom: var(--ds-space-3);
}

.ds-results-meta__label {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  margin: 0;
}

@media (max-width: 767px) {
  .ds-filter-bar {
    padding: var(--ds-space-4);
  }

  /* Row 1 collapses to [query | Filter (n)]; count + sort wrap below. */
  .ds-filter-bar__query {
    flex: 1 1 55%;
  }

  .ds-filter-bar__mobile-toggle {
    display: inline-flex;
    min-height: 44px;
  }

  .ds-filter-bar__apply,
  .ds-filter-bar__reset {
    display: none;
  }

  .ds-filter-bar__sort {
    flex: 1 1 auto;
    min-height: 44px;
  }

  body.ds-filter-sheet-open {
    overflow: hidden;
  }

  /* The group container becomes a full-screen sheet. */
  .ds-filter-bar__groups {
    position: fixed;
    inset: 0;
    z-index: var(--ds-z-modal);
    display: none;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
    background: var(--ds-surface);
    overflow-y: auto;
    padding: 0 var(--ds-space-4) var(--ds-space-4);
  }

  body.ds-filter-sheet-open .ds-filter-bar__groups {
    display: flex;
  }

  .ds-filter-bar__sheet-head {
    position: sticky;
    top: 0;
    z-index: var(--ds-z-base);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-space-3);
    background: var(--ds-surface);
    padding: var(--ds-space-3) 0;
    border-bottom: 1px solid var(--ds-border-subtle);
  }

  .ds-filter-bar__sheet-title {
    font-size: var(--ds-text-subsection);
    font-weight: var(--ds-fw-bold);
    color: var(--ds-ink);
  }

  .ds-filter-bar__sheet-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    border: 0;
    background: none;
    color: var(--ds-ink);
    font-size: var(--ds-text-lg);
    cursor: pointer;
    border-radius: var(--ds-radius-sm);
  }

  /* The toast overlays the whole site header on a phone, so the control that
     dismisses it has to meet the same 44px floor as every other close button
     — it was the one control still sized 28px. */
  .ls-toast-close {
    min-width: 44px;
    min-height: 44px;
  }

  /* .ds-form-help carries the only explanation on several screens (the wish
     status, the export failure reason, the consent error). At caption size it
     was the smallest text on the page precisely where it mattered most. */
  .ds-form-help {
    font-size: var(--ds-text-body-sm);
  }

  .ds-filter-bar__sheet-close:focus-visible {
    outline: none;
    box-shadow: var(--ds-shadow-focus);
  }

  /* Groups render as full-width accordion rows inside the sheet. */
  .ds-filter-group {
    position: static;
  }

  .ds-filter-group__toggle {
    width: 100%;
    min-height: 44px;
    border: 0;
    border-bottom: 1px solid var(--ds-border-subtle);
    border-radius: 0;
    background: none;
    padding: var(--ds-space-3) 0;
    font-size: var(--ds-text-body);
  }

  .ds-filter-group.is-open > .ds-filter-group__toggle {
    background: none;
  }

  .ds-filter-group__toggle .bi-chevron-down {
    margin-left: auto;
  }

  .ds-filter-group__panel,
  .ds-filter-group__panel--wide,
  .ds-filter-group__panel--end {
    position: static;
    width: 100%;
    /* The edge guard is a popover concern; in the sheet the panel is a
       full-width accordion pane and any leftover shift would misalign it. */
    margin-left: 0;
    margin-right: 0;
    max-height: none;
    overflow: visible;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: var(--ds-space-3) 0 var(--ds-space-4);
  }

  .ds-filter-group__grid {
    grid-template-columns: 1fr;
    gap: var(--ds-space-4);
  }

  /* Per-panel apply buttons are redundant under the sticky sheet apply. */
  .ds-filter-group__foot {
    display: none;
  }

  .ds-filter-bar__sheet-foot {
    position: sticky;
    bottom: 0;
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-2);
    margin-top: auto;
    background: var(--ds-surface);
    border-top: 1px solid var(--ds-border-subtle);
    padding: var(--ds-space-3) 0 var(--ds-space-2);
  }
}

/* Auth split-layout (.auth-shell / .auth-brand-side) removed in Spec C — use .auth-minimal instead. */

/* === Activity-Stream === */
.activity-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.activity-list li {
  padding: 0.75rem 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid var(--ds-border-gray);
  font-size: var(--ds-text-body-sm);
}
.activity-list li:last-child {
  border-bottom: 0;
}
.activity-list a {
  color: var(--ds-ink);
  text-decoration: none;
  font-weight: var(--ds-fw-semi);
}
.activity-list a:hover {
  color: var(--ds-blue);
}
.activity-list .activity-time {
  color: var(--ds-ink-soft);
  font-size: 0.82rem;
  flex-shrink: 0;
}

/* === Mobile App-Tweaks === */

/* === Empty-State === */

/* Welcome hero banner (replaces the old app-page-header) */

.ds-app-eyebrow-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ds-success-bright);
  box-shadow: 0 0 0 4px rgba(var(--ds-success-bright-rgb), 0.18);
  animation: appPremEyebrowPulse 1.6s ease-in-out infinite;
}

@keyframes appPremEyebrowPulse {
  0%,
  100% {
    box-shadow: 0 0 0 4px rgba(var(--ds-success-bright-rgb), 0.18);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(var(--ds-success-bright-rgb), 0);
  }
}
/* Activity list row hover */
.app-shell .activity-list li {
  border-radius: var(--ds-radius-sm);
  padding: var(--ds-space-3) var(--ds-space-3-5);
  margin: 0 -14px;
  transition: background 0.2s;
}

.app-shell .activity-list li:hover {
  background: rgba(var(--ds-blue-rgb), 0.04);
}

/* ============================================================
   Global Consistency Pass (mirrors leadsuche.css)
   Smoother hover transitions across all app-shell cards
   ============================================================ */

.app-shell .activity-list li {
  transition:
    transform 0.5s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.5s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.4s ease,
    background-color 0.3s ease;
  will-change: transform;
}

/* ============================================================
   Single-column app-page layout helper — centres a narrow
   content column under a header (e.g. the e-mail-preferences page).
   ============================================================ */
.app-container--narrow {
  max-width: 720px;
}

/* The app-hero pulls -12px on each side to sit flush with the Bootstrap-row
   gutter. A plain content card below it would otherwise sit 12px narrower on
   each side, so on this narrow single-column page (the only --narrow user) the
   card matches the hero's full width with the same gutter pull. */
.app-container--narrow > .ds-card {
  margin-left: -12px;
  margin-right: -12px;
}

/* Container for form submit buttons at the bottom of a card */
.ds-app-card-actions {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--ds-border-gray);
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* Alert-state eyebrow (credits_locked.html). Paints the eyebrow pill
   in the Phase-2 danger tone with a matching halo — semantic colour
   for the "wallet empty" state. */
.ds-app-eyebrow--alert {
  color: var(--ds-danger);
}
.ds-app-eyebrow--alert .ds-app-eyebrow-dot {
  background: var(--ds-danger);
  box-shadow: 0 0 0 4px var(--ds-danger-tint);
}

/* Lead-qualification highlight quote (unlocked_detail.html). Replaces
   the inline-styled blockquote with a tokenised rendering. */
.lead-highlight-quote {
  border-left: 3px solid var(--ds-blue);
  padding: 0.5rem 0 0.5rem 1rem;
  margin: 1rem 0;
  font-style: italic;
  color: var(--ds-ink);
  background: var(--ds-border-subtle);
  border-radius: 0 var(--ds-radius-sm) var(--ds-radius-sm) 0;
}

/* Text colour helpers that aren't covered by Bootstrap utilities. */

.ds-auth-card__heading {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  margin: 0 0 var(--ds-space-2);
  text-align: center;
  color: var(--ds-ink);
}

.ds-auth-card__lead {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  text-align: center;
  margin: 0 0 var(--ds-space-6);
}

/* Auth-card footer strip (divider + caption text + optional link). */
.ds-auth-card__footer {
  margin-top: var(--ds-space-5);
  padding-top: var(--ds-space-4);
  border-top: 1px solid var(--ds-border-subtle);
  text-align: center;
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-soft);
}

/* Inline anchor inside .ds-auth-card__footer and forgot-password row. */
.ds-auth-card__link {
  color: var(--ds-blue);
  font-weight: var(--ds-fw-semi);
}

/* Forgot-password / secondary-action row above the footer divider. */
.ds-auth-card__action-hint {
  margin-top: var(--ds-space-4);
  text-align: center;
  font-size: var(--ds-text-caption);
}

/* Centered icon circle used on status/confirmation cards (64 × 64 px). */
.ds-auth-card__icon {
  width: 64px;
  height: 64px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--ds-radius-full);
  font-size: 28px;
  margin: 0 auto var(--ds-space-4);
}

/* Colour modifiers for .ds-auth-card__icon. */
.ds-auth-card__icon--brand {
  background: var(--ds-gradient-brand-soft);
  color: var(--ds-blue);
}

.ds-auth-card__icon--danger {
  background: var(--ds-danger-tint);
  color: var(--ds-danger);
}

.ds-auth-card__icon--success {
  background: var(--ds-success-tint);
  color: var(--ds-success);
}

/* Modifier that centres all direct children inside a ds-auth-card. */
.ds-auth-card--centered {
  text-align: center;
}

/* Feature-aside benefit list (replaces inline-styled ul/li/i patterns). */
.ds-auth-card__aside-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
}

.ds-auth-card__aside-list li {
  display: flex;
  gap: var(--ds-space-3);
  align-items: flex-start;
}

.ds-auth-card__aside-list i {
  color: var(--ds-blue);
  flex-shrink: 0;
}

/* Small footnote below the aside list (e.g. "no auto-renewal" note). */
.ds-auth-card__footnote {
  margin: var(--ds-space-4) 0 0;
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
}

/* Token-driven text-colour utilities (brand ramp for status/muted text). */
.ds-text-success {
  color: var(--ds-success);
}

.ds-text-danger {
  color: var(--ds-danger);
}

.ds-text-brand {
  color: var(--ds-blue);
}

.ds-text-sm {
  font-size: var(--ds-text-body-sm);
}

/* Token-clean pagination component (replaces Bootstrap .pagination defaults). */
.ds-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--ds-space-3);
  margin-top: var(--ds-space-6);
  flex-wrap: wrap;
}

.ds-pagination__link {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-2) var(--ds-space-4);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-sm);
  color: var(--ds-ink);
  text-decoration: none;
  font-size: var(--ds-text-body-sm);
  font-weight: var(--ds-fw-semi);
  transition:
    border-color var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out),
    background var(--ds-dur-fast) var(--ds-ease-out);
}

.ds-pagination__link:hover,
.ds-pagination__link:focus-visible {
  border-color: var(--ds-blue);
  color: var(--ds-blue);
}

.ds-pagination__link--disabled {
  color: var(--ds-ink-mute);
  background: var(--ds-surface-tint);
  cursor: not-allowed;
}

.ds-pagination__link--disabled:hover {
  border-color: var(--ds-border-subtle);
  color: var(--ds-ink-mute);
}

/* Current page in numbered pagination rows (blog index page numbers). */
.ds-pagination__link--active {
  background: var(--ds-blue);
  border-color: var(--ds-blue);
  color: var(--ds-white);
  pointer-events: none;
}

.ds-pagination__status {
  font-size: var(--ds-text-body-sm);
  color: var(--ds-ink-soft);
  font-weight: var(--ds-fw-semi);
  padding: 0 var(--ds-space-2);
}

/* Phones: tighter gaps and no wrapping so prev/status/next stay on one row
   ("Weiter" used to orphan onto a second line at 390px). The 44px link
   height comes from the shared mobile touch-target block. */
@media (max-width: 575px) {
  .ds-pagination {
    flex-wrap: nowrap;
    gap: var(--ds-space-2);
  }
  .ds-pagination__link {
    padding-inline: var(--ds-space-3);
  }
  .ds-pagination__status {
    white-space: nowrap;
  }
}

/* Token-clean inline spinner (replaces Bootstrap .spinner-border).
   Pairs with badges, buttons, and any inline status surface. */
.ds-spinner {
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.1em;
  animation: spin 0.7s linear infinite;
}

.ds-spinner--sm {
  width: 0.8em;
  height: 0.8em;
  border-width: 1.5px;
}
.ds-spinner--lg {
  width: 1.4em;
  height: 1.4em;
  border-width: 2px;
}

/* ============================================================================
 * M3 · Dashboard welcome hero (dark section on app shell)
 * Structure: <section class="section-dark app-welcome" data-motion="app-welcome">
 * Wires: heroCharReveal3D + cursorFollowGlow via LSMotion.init()
 * ============================================================================ */

/* ============================================================================
 * M4 · Filter dock — dark utility sidebar for lead search
 * Structure: <aside class="filter-dock section-dark section-dark--utility">
 * ============================================================================ */

/* The lead-detail family. Deliberately a single readable column rather than
   the two-column grid the earlier unprefixed selectors used — those were
   removed once the aside turned out to only duplicate the hero actions.
   Consumed by unlock/unlocked_detail.html. */
.ds-lead-detail {
  /* Single readable column — the former aside only duplicated the hero
       actions and left an empty flank over the full scroll. The 960px cap
       is a content-driven measure: the KV/score grids auto-fit to three or
       four columns inside it while prose sections keep a readable line
       length. */
  max-width: 960px;
  margin-top: clamp(1rem, 2vh, 1.5rem);
  margin-inline: auto;
}

.ds-lead-detail__main {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.6vh, 20px);
  min-width: 0;
}

.ds-lead-detail__hero {
  position: relative;
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  background: linear-gradient(
    180deg,
    var(--ds-white) 0%,
    var(--ds-surface-tint) 100%
  );
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-lg);
  box-shadow: 0 10px 30px -18px rgba(var(--ds-blue-rgb), 0.22);
  overflow: hidden;
}

.ds-lead-detail__hero::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(
    135deg,
    var(--ds-blue) 0%,
    var(--ds-purple) 60%,
    var(--ds-red) 100%
  );
}

.ds-lead-detail__company {
  font-family: var(--ds-font-display);
  font-size: clamp(1.45rem, 2.4vw, 1.9rem);
  letter-spacing: var(--ds-tracking-tight);
  line-height: 1.12;
  font-weight: var(--ds-fw-black);
  color: var(--ds-ink);
  margin: 0 0 0.5rem;
}

.ds-lead-detail__section {
  position: relative;
  padding: clamp(1.1rem, 2vw, 1.5rem);
  background: var(--ds-surface);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.1);
  border-radius: var(--ds-radius-lg);
  box-shadow: 0 4px 14px -10px rgba(var(--ds-blue-rgb), 0.12);
}

/* Meta-chip row — industry/legal_form/country/status shown under the hero. */
.ds-detail-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-2);
}

.ds-detail-meta__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  padding: 5px 12px;
  background: rgba(var(--ds-blue-rgb), 0.06);
  border: 1px solid rgba(var(--ds-blue-rgb), 0.14);
  border-radius: var(--ds-radius-full);
  font-size: 0.82rem;
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink);
}

.ds-detail-meta__chip i {
  color: var(--ds-blue);
  font-size: var(--ds-text-body-sm);
}

/* The unlocked-state chip carries tabindex="0" so its tooltip is reachable
   by keyboard; being a span, none of the global focus fallbacks apply. */
.ds-detail-meta__chip:focus-visible {
  outline: none;
  box-shadow: var(--ds-shadow-focus);
}

.ds-detail-meta__chip--success {
  background: rgba(var(--ds-success-rgb), 0.08);
  border-color: rgba(var(--ds-success-rgb), 0.28);
  color: var(--ds-success-deep);
  margin-left: auto;
}

.ds-detail-meta__chip--success i {
  color: var(--ds-success);
}

/* Section header inside a detail card — icon-tile + title. */
.ds-detail-section__header {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2-5);
  margin-bottom: var(--ds-space-3-5);
}

.ds-detail-section__icon {
  width: 34px;
  height: 34px;
  border-radius: var(--ds-radius-sm);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.12),
    rgba(var(--ds-purple-rgb), 0.1)
  );
  color: var(--ds-blue);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  flex-shrink: 0;
}

.ds-detail-section__title {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
  letter-spacing: -0.01em;
}

/* Key-Value grid — responsive; each kv reads as a soft info-tile. */
.ds-detail-kv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--ds-space-3);
}

.ds-detail-kv {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-1);
  padding: var(--ds-space-3) var(--ds-space-3-5);
  background: linear-gradient(
    180deg,
    var(--ds-surface-tint, var(--ds-surface-tint)) 0%,
    var(--ds-surface) 100%
  );
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-sm);
}

.ds-detail-kv__label {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1-5);
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
}

.ds-detail-kv__label i {
  color: var(--ds-blue);
  font-size: var(--ds-text-caption);
}

.ds-detail-kv__value {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-semi);
  color: var(--ds-ink);
  line-height: 1.4;
  word-break: break-word;
}

.ds-detail-kv__value a {
  color: var(--ds-blue);
  text-decoration: none;
  font-weight: var(--ds-fw-semi);
}

.ds-detail-kv__value a:hover {
  text-decoration: underline;
}

.ds-detail-kv__value--muted {
  color: var(--ds-ink-mute);
  font-weight: var(--ds-fw-medium);
}

/* Scoring cards — gradient number, compact footprint. */
.ds-scorecard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: var(--ds-space-3);
}

.ds-scorecard {
  padding: var(--ds-space-3-5) var(--ds-space-3);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.05),
    rgba(var(--ds-purple-rgb), 0.03)
  );
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius-md);
  text-align: center;
}

.ds-scorecard__label {
  font-size: var(--ds-text-eyebrow);
  font-weight: var(--ds-fw-bold);
  letter-spacing: var(--ds-tracking-meta);
  text-transform: uppercase;
  color: var(--ds-ink-mute);
  margin-bottom: var(--ds-space-1-5);
}

.ds-scorecard__value {
  font-family: var(--ds-font-display);
  font-size: 1.9rem;
  font-weight: var(--ds-fw-black);
  line-height: 1;
  letter-spacing: var(--ds-tracking-tight);
  background: var(--ds-gradient-icon-tile);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--ds-blue);
}

.ds-scorecard__suffix {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-medium);
  color: var(--ds-ink-mute);
  -webkit-text-fill-color: var(--ds-ink-mute);
  margin-left: var(--ds-space-0-5);
}

.ds-scorecard__value--text {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  -webkit-text-fill-color: var(--ds-ink);
  background: none;
  -webkit-background-clip: initial;
  background-clip: initial;
  line-height: 1.3;
}

/* Highlight quote — italicized pull-quote with gradient accent bar. */
.ds-highlight-quote {
  margin: var(--ds-space-3-5) 0 0;
  padding: var(--ds-space-3-5) var(--ds-space-4-5);
  background: linear-gradient(
    135deg,
    rgba(var(--ds-blue-rgb), 0.05),
    rgba(var(--ds-purple-rgb), 0.03)
  );
  border-left: 3px solid var(--ds-blue);
  border-radius: 0 var(--ds-radius-sm) var(--ds-radius-sm) 0;
  font-size: var(--ds-text-body);
  font-style: italic;
  color: var(--ds-ink-soft);
  line-height: 1.55;
}

/* Tech-stack badge row. */
.ds-detail-techstack {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
}

/* Profile prose block. */
.ds-detail-prose {
  margin: 0;
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body);
  line-height: 1.6;
}

/* ============================================================================
 * M5 · Empty state — premium illustrated placeholder
 * ============================================================================ */

@keyframes emptyStateFloat {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4px);
  }
}

/* ============================================================================
 * HOME — Landing page in the dashboard visual language.
 * All home modules reuse the shared dashboard card styling; only the
 * home-specific extensions live here (hero stats, problem grid,
 * use-case/feature/industry grids, pricing cards, top-ups, FAQ accordion,
 * final CTA).
 * ============================================================================ */

/* === A11y-Post-Migration Token-Typography Fix === */

/* Inline <code> within prose / section-leads — ensures WCAG AA on light surfaces.
   Bootstrap default is pink #d63384 which fails 4.5:1 on --ds-surface-tint.
   Excludes eyebrow-pills (already 11px — 0.92em would drop to 10.12px). */
.ds-section__lead code,
.ds-prose code,
.ds-section code:not(pre code):not(.ds-eyebrow code) {
  color: var(--ds-ink);
  background: rgba(var(--ds-blue-rgb), 0.08);
  padding: 1px 6px;
  border-radius: var(--ds-radius-xs);
  font-size: 0.92em;
  font-family: var(--ds-font-mono);
  font-weight: var(--ds-fw-semi);
}

.ds-eyebrow code {
  font-size: inherit;
  font-family: var(--ds-font-mono);
  background: transparent;
  padding: 0;
  color: inherit;
  font-weight: inherit;
}

/* Standalone links inside text-blocks — explicit underline + color for distinction
   from surrounding text (WCAG 1.4.1 non-color-dependent). */
.ds-section__lead a:not(.ds-button):not(.ds-badge),
.ds-prose a:not(.ds-button):not(.ds-badge),
p a:not(.ds-button):not(.ds-badge) {
  color: var(--ds-blue);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: var(--ds-fw-semi);
}
.ds-section__lead a:not(.ds-button):not(.ds-badge):hover,
.ds-prose a:not(.ds-button):not(.ds-badge):hover,
p a:not(.ds-button):not(.ds-badge):hover {
  color: var(--ds-purple);
}

/* ============================================================================
 * Table scroll affordance (C3.2) — shared pattern for every horizontal
 * table scroller. Two signals: (1) an always-styled horizontal scrollbar,
 * (2) scroll shadows via the background-attachment trick — the inner edge
 * shadow only shows while content is actually cut off, because the local-
 * attached cover layer slides over it at the scroll ends.
 * ========================================================================== */

.ds-table-wrap,
.ds-lead-table-wrap {
  background:
    linear-gradient(90deg, var(--ds-surface) 30%, rgba(var(--ds-white-rgb), 0))
      left center / 48px 100% no-repeat local,
    linear-gradient(270deg, var(--ds-surface) 30%, rgba(var(--ds-white-rgb), 0))
      right center / 48px 100% no-repeat local,
    radial-gradient(
        farthest-side at 0 50%,
        rgba(var(--ds-ink-rgb), 0.35),
        transparent
      )
      left center / 22px 100% no-repeat scroll,
    radial-gradient(
        farthest-side at 100% 50%,
        rgba(var(--ds-ink-rgb), 0.35),
        transparent
      )
      right center / 22px 100% no-repeat scroll var(--ds-surface);
  scrollbar-width: thin;
  scrollbar-color: var(--ds-surface-4) var(--ds-surface-tint);
}

.ds-table-wrap::-webkit-scrollbar,
.ds-lead-table-wrap::-webkit-scrollbar {
  height: 8px;
}

.ds-table-wrap::-webkit-scrollbar-track,
.ds-lead-table-wrap::-webkit-scrollbar-track {
  background: var(--ds-surface-tint);
  border-radius: var(--ds-radius-full);
}

.ds-table-wrap::-webkit-scrollbar-thumb,
.ds-lead-table-wrap::-webkit-scrollbar-thumb {
  background: var(--ds-surface-4);
  border-radius: var(--ds-radius-full);
}

/* A ds-compare-table inside a scroll wrap brings its own border/shadow and
   needs headroom for the FAVORIT badge — the wrap recedes to a pure scroll
   container in that case (used by the reference-page demos). */
.ds-table-wrap:has(> .ds-compare-table) {
  border: none;
  box-shadow: none;
  padding-top: var(--ds-space-3-5);
}

/* Code demos share the always-visible scrollbar affordance. */
pre {
  scrollbar-width: thin;
  scrollbar-color: var(--ds-surface-4) transparent;
}

pre::-webkit-scrollbar {
  height: 8px;
}

pre::-webkit-scrollbar-thumb {
  background: var(--ds-surface-4);
  border-radius: var(--ds-radius-full);
}

/* ============================================================================
 * Lead-Table card collapse (C3.2 / C2.3 dual canon) — opt-in via the
 * .ds-lead-table--cards + .ds-lead-table-wrap--cards modifiers. Below 768px
 * each row renders as a ds-card--lead-style stacked card (company name,
 * location/industry/employees, contact icons, score pills, action) instead
 * of a 700px horizontal-scroll table. The per-cell element classes are set
 * in templates/leads/search.html; tables without the modifier keep the
 * scroll-wrapper strategy.
 * ========================================================================== */

@media (max-width: 767px) {
  .ds-lead-table-wrap--cards {
    overflow: visible;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
  }

  .ds-lead-table--cards {
    display: block;
    min-width: 0;
  }

  .ds-lead-table--cards thead {
    display: none;
  }

  .ds-lead-table--cards tbody {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-3);
  }

  .ds-lead-table--cards tbody tr {
    display: block;
    position: relative;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border-subtle);
    border-radius: var(--ds-radius-md);
    box-shadow: var(--ds-shadow-sm);
    padding: var(--ds-space-4);
  }

  .ds-lead-table--cards tbody tr:hover {
    background: var(--ds-surface);
  }

  .ds-lead-table--cards td {
    display: inline-block;
    border: 0;
    padding: 0;
    vertical-align: middle;
  }

  /* Card header: company name spans the row; the action button floats
       top-right, so the cell reserves space for it. */
  .ds-lead-table--cards td.ds-lead-table__cell--company {
    display: block;
    padding-right: var(--ds-space-12);
    margin-bottom: var(--ds-space-2);
  }

  /* Long unbroken company names must wrap inside the narrow card instead of
       overflowing it; flex-start keeps the icon aligned to the first line. */
  .ds-lead-table--cards .ds-lead-table__company {
    min-width: 0;
    overflow-wrap: anywhere;
    align-items: flex-start;
  }

  .ds-lead-table--cards td.ds-lead-table__cell--location,
  .ds-lead-table--cards td.ds-lead-table__cell--industry {
    margin: 0 var(--ds-space-3) var(--ds-space-2) 0;
  }

  /* Size/employees is table-hidden via hide-md at this width, but the
       card spec includes it — re-show inside the card. */
  .ds-lead-table--cards td.ds-lead-table__cell--size {
    display: inline-block;
    margin: 0 var(--ds-space-3) var(--ds-space-2) 0;
  }

  /* Secondary columns stay hidden in card mode. */
  .ds-lead-table--cards td.ds-lead-table__cell--market,
  .ds-lead-table--cards td.ds-lead-table__cell--revenue,
  .ds-lead-table--cards td.ds-lead-table__cell--web {
    display: none;
  }

  .ds-lead-table--cards td.ds-lead-table__cell--contact {
    display: inline-block;
    margin: 0 var(--ds-space-4) var(--ds-space-1) 0;
  }

  .ds-lead-table--cards td.ds-lead-table__cell--score {
    display: inline-block;
    margin-bottom: var(--ds-space-1);
  }

  .ds-lead-table--cards td.ds-lead-table__cell--action {
    position: absolute;
    top: var(--ds-space-3);
    right: var(--ds-space-3);
    padding: 0;
  }

  /* Row-selection checkbox (unlocked list): pinned top-left; the company
       header cell indents to clear it. */
  .ds-lead-table--cards td.ds-lead-table__row-select {
    position: absolute;
    top: var(--ds-space-4);
    left: var(--ds-space-4);
    width: auto;
    padding: 0;
  }

  .ds-lead-table--cards
    td.ds-lead-table__row-select
    ~ td.ds-lead-table__cell--company {
    padding-left: var(--ds-space-10);
  }
}

/* ============================================================================
 * Mobile floor & touch targets (C3.2/C3.3) — 44px interactive floor < 768px.
 * Grouped here so every undersized control shares one documented fix.
 * ========================================================================== */

@media (max-width: 767px) {
  /* Every button gains the 44px hit box. The floor used to be applied to
       --sm only, which left the base .ds-button at 35px (9px padding + a
       1.2 line-height on the 14px body-sm scale) — so the compact variant
       rendered TALLER than the primary and secondary actions it is meant
       to de-emphasise. The type scale and padding are untouched; only the
       hit area grows. */
  .ds-button {
    min-height: 44px;
  }

  /* Icon-only compact buttons (table row actions, chip removers) satisfy the
       height floor but stay 36px wide. A square target needs the floor on
       both axes; buttons carrying a text label are already wider. */
  .ds-button--sm:not(:has(> :not(i):not(svg))) {
    min-width: 44px;
  }

  /* Header brand: the header is 80px tall, only the anchor box was
       short — extend its own hit area without moving the layout. */
  .ds-site-header__brand {
    min-height: 44px;
  }

  /* The two app-header controls next to the burger. Both are permanent
       fixtures of the logged-in shell and both sat under the floor (badge
       32px, avatar 36px); the header has the vertical room, so only the
       hit area grows. */
  .ds-wallet-badge {
    min-height: 44px;
  }

  .ds-avatar-menu {
    width: 44px;
    height: 44px;
  }

  /* Mobile-nav burger: the primary mobile menu/drawer trigger — raise its
       32px glyph box to the 44px touch floor (the 20px SVG stays centered). */
  .ds-site-header__burger {
    width: 44px;
    height: 44px;
  }

  /* Footer link rows: minimal app footer, marketing footer columns and
       the legal strip (incl. the consent re-open button). */
  .ds-app-footer__links a,
  .ds-app-footer__links .ds-footer-link-button,
  .ds-site-footer__legal-links a,
  .ds-site-footer__legal-links .ds-footer-link-button {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .ds-site-footer__col a {
    min-height: 44px;
  }

  /* Pagination links (blog index, search, unlocked list). Numbered page
       links are narrow, so the floor applies to both axes. */
  .ds-pagination__link {
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
  }

  /* Auth-card secondary links ("Zurück zur Anmeldung", "Passwort
       vergessen?") render as bare 15px text otherwise. */
  .ds-auth-card__link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Inline links inside check labels (consent checkboxes) deliberately carry
       NO vertical padding — for the same reason the consent banner's privacy
       link never did. Vertical padding on an inline element does not grow its
       line box, so a 46px hit area inside a 21px line overlaps the next line
       by 25px. On the signup label ("… die AGB und die Datenschutzerklärung.")
       the two links land on consecutive lines, the later one paints on top,
       and "AGB" loses its lower half including its own centre point: aiming at
       the terms opened the privacy policy. A 44px target is unreachable here
       by construction — clearing it would need a line-height of 46px on a
       consent row — and both links sit in a running sentence, which WCAG 2.2
       SC 2.5.8 exempts from the target-size floor. */

  /* Footer back-to-top control — a button-shaped target rendered at 32px. */
  .ds-site-footer__to-top {
    min-height: 44px;
  }

  /* The dashboard's "Weiter einrichten" continuation link: a standalone call
       to action at the caption scale, not an inline link inside a sentence,
       so the floor applies. Negative block margin keeps the surrounding
       baseline row at its current height — same idiom as .ds-card__header a
       above. */
  /* Also covers the class-less direct-child links (the plans page's
     "Details" measured 46x21). `.ds-alert` is a flex container, so a direct
     child is a flex item and not a link inside running text — the floor can
     apply here without the line-overlap that rules it out for inline links. */
  .ds-alert a.small,
  .ds-alert > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -12px;
  }

  /* Unlocked-detail payoff links (Website / E-Mail / Telefon). */
  .ds-detail-kv__value a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Blog category chips are explicitly named by the contract's 44px rule. */
  .cluster-chip {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: var(--ds-space-2-5) var(--ds-space-4);
  }

  /* Card-header inline actions ("Alle anzeigen") and the recent-unlock
       list rows on the dashboard. */
  .ds-card__header a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -10px;
  }

  .activity-list a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Breadcrumb links (blog articles) — negative margins keep the visual
       rhythm while the hit box meets the 44px floor in both axes. */
  .ds-breadcrumb a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
    margin-block: -12px;
    margin-inline: -4px;
  }

  /* Company-name links inside lead/record tables. */
  .ds-lead-table td a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -11px;
  }

  /* Inline prose links (mail addresses, body links): vertical tap padding
       extends the hit box without moving the inline line box. */
  p a:not(.ds-button):not(.ds-badge),
  .ds-prose a:not(.ds-button):not(.ds-badge) {
    padding-block: 12px;
  }

  /* Row-select, filter, consent and preference checkboxes: enlarge the
       visible box; the surrounding label/row carries the rest of the hit
       area. */
  .ds-lead-table__row-select input[type="checkbox"],
  .form-check-input {
    width: 24px;
    height: 24px;
  }

  /* Checkbox/radio inputs additionally get an invisible hit-area
       extension around the 24px visual box (-10px on each side = 44px
       effective target) — covers the label-less row-select variant where
       no text area widens the wrapping ds-check label. */
  .ds-check__input {
    position: relative;
  }

  .ds-check__input::after {
    content: "";
    position: absolute;
    inset: -10px;
  }

  /* Applied-filter remove chips are named explicitly by the contract's
       44px rule. */
  .ds-filter-chip {
    min-height: 44px;
  }

  /* Sticky sheet footer of the mobile filter sheet (apply + reset). */
  .ds-filter-bar__sheet-foot .ds-button {
    min-height: 44px;
  }

  /* Badge-shaped links (e.g. reference-page TOC chips): invisible
       vertical hit-area extension that leaves the visual size untouched. */
  a.ds-badge {
    position: relative;
  }

  a.ds-badge::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Sticky-CTA dismiss control. */
  .ds-sticky-cta-close {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Delete-account modal dismiss control (includes/_modal_delete_account). */
  .ds-modal__close {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Data-table cells tighten so the first scroll viewport ends near a
       column boundary instead of mid-element. */
  .ds-table thead th,
  .ds-table tbody td {
    padding: var(--ds-space-3);
  }

  /* Row actions inside scrolling data tables go icon-only — the full
       label would be cut mid-button at the wrap edge; the accessible name
       stays on the control via aria-label/title. */
  .ds-table__action-label {
    display: none;
  }

  .ds-table__actions-cell .ds-button {
    min-width: 44px;
    justify-content: center;
  }
}

/* ds-modal — minimal overlay component used for destructive-action confirms.
   Driven by static/js/modals.js (data-ds-modal-open/close attributes). */
.ds-modal[hidden] {
  display: none;
}
.ds-modal {
  position: fixed;
  inset: 0;
  z-index: var(--ds-z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--ds-space-6);
}
.ds-modal__overlay {
  position: absolute;
  inset: 0;
  background: rgba(var(--ds-ink-rgb), 0.55);
  backdrop-filter: blur(2px);
  cursor: pointer;
}
.ds-modal__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 520px;
  /* The container is fixed/inset-0 with 24px padding, so the panel has to
     measure against the *visible* viewport. 100vh is the large viewport on
     mobile, which would let the panel outgrow its centred container and clip
     the close and confirm controls off both ends. */
  max-height: calc(100svh - 48px);
  overflow-y: auto;
  background: var(--ds-white);
  border-radius: var(--ds-radius-sm);
  box-shadow: var(--ds-shadow-modal);
  padding: var(--ds-space-6);
}

@supports not (max-height: 100svh) {
  .ds-modal__panel {
    max-height: calc(100vh - 48px);
  }
}

.ds-modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ds-space-4);
  margin-bottom: var(--ds-space-4);
}
.ds-modal__title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  margin: 0;
  color: var(--ds-ink);
}
.ds-modal__close {
  background: transparent;
  border: 0;
  font-size: 24px;
  line-height: 1;
  color: var(--ds-ink);
  cursor: pointer;
  padding: var(--ds-space-1);
  border-radius: var(--ds-radius-xs);
  transition:
    background var(--ds-dur-fast) var(--ds-ease-out),
    color var(--ds-dur-fast) var(--ds-ease-out);
}
.ds-modal__close:hover,
.ds-modal__close:focus-visible {
  background: rgba(var(--ds-ink-rgb), 0.08);
}
.ds-modal__body {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
}
.ds-modal__footer {
  display: flex;
  justify-content: flex-end;
  /* At 320px the two actions of the delete-account dialog share 212px, which
     leaves "Abbrechen" 97px for a 105px word — clipped, since .ds-button hides
     its overflow for the hover sheen. Wrapping gives each action the full row
     instead of cutting the label; above ~360px both still fit side by side. */
  flex-wrap: wrap;
  gap: var(--ds-space-3);
  margin-top: var(--ds-space-5);
  padding-top: var(--ds-space-3);
  border-top: 1px solid var(--ds-surface-3);
}
body.ds-modal-open {
  overflow: hidden;
}

/* ============================================================
   ds-progress — token-driven progress bar component.
   Replaces raw Bootstrap .progress / .progress-bar classes
   in app-shell templates (e.g. onboarding completion tracker).
   The track height is baked into the component; the fill width
   is set via an inline style="width: X%" on .ds-progress__bar
   because it is driven by a server-computed percentage value.
   ============================================================ */
.ds-progress {
  height: 8px;
  border-radius: var(--ds-radius-full);
  background: var(--ds-surface-muted);
  overflow: hidden;
}

.ds-progress__bar {
  height: 100%;
  border-radius: var(--ds-radius-full);
  background: var(--ds-blue);
  transition: width var(--ds-dur-slow) var(--ds-ease-out);
}

/* ============================================================
   ds-app-card-footnote — muted caption line below a form card.
   Renders privacy / label references at reduced prominence.
   ============================================================ */
.ds-app-card-footnote {
  margin-top: var(--ds-space-4);
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  line-height: 1.55;
}

/* ============================================================
   ds-orb position/size modifiers — replaces per-instance
   inline styles on decorative background orbs.
   Each modifier encodes the section and colour so the values
   stay maintainable and the HTML stays attribute-free.
   ============================================================ */
.ds-orb--hero-blue {
  top: -14%;
  left: -8%;
  width: 620px;
  height: 620px;
}
.ds-orb--hero-purple {
  bottom: -22%;
  right: -12%;
  width: 580px;
  height: 580px;
}
.ds-orb--hero-cyan {
  top: 38%;
  right: 22%;
  width: 340px;
  height: 340px;
}

.ds-orb--solution-purple {
  top: 10%;
  right: -10%;
  width: 460px;
  height: 460px;
}
.ds-orb--solution-blue {
  bottom: -10%;
  left: -5%;
  width: 420px;
  height: 420px;
}

.ds-orb--usecases-blue {
  top: 0;
  left: -10%;
  width: 440px;
  height: 440px;
}
.ds-orb--usecases-red {
  bottom: -10%;
  right: -5%;
  width: 360px;
  height: 360px;
  opacity: 0.2;
}

/* ============================================================
   ds-hero__lead--secondary — secondary lead paragraph variant.
   Slightly smaller and softer than the primary lead paragraph
   to create visual hierarchy without a separate component.
   No --ds-* token exists for this specific 0.95 em step-down;
   the value is intentionally close-to-1em and maintenance-safe.
   ============================================================ */
.ds-hero__lead--secondary {
  font-size: 0.95em;
  opacity: 0.82;
}

/* ============================================================
   ul.ds-feature-grid — list-reset when ds-feature-grid is
   applied to a <ul> element.  Keeps the component stylesheet
   correct regardless of the host element semantics.
   ============================================================ */
ul.ds-feature-grid {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* ============================================================================
 * ds-demo-* — /design/ reference-page showcase scaffolding (C2.6)
 * Page-internal utilities used ONLY by templates/core/design_system.html to
 * lay out component demos without inline styles. Token-composed; never use
 * these classes in product templates — they document nothing and may change
 * with the reference page.
 * ========================================================================== */

/* Left-aligned section headers (the reference page reads as a document). */
.ds-demo-title {
  text-align: left;
}
.ds-demo-lead {
  text-align: left;
  margin-left: 0;
}

/* Eyebrow label above a demo block. */
.ds-demo-label {
  display: block;
  margin-bottom: var(--ds-space-2);
}

/* Generic demo layout: wrapping flex row and vertical stack. */
.ds-demo-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-3);
  align-items: center;
}
.ds-demo-row--center {
  justify-content: center;
}
.ds-demo-stack {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-6);
}
.ds-demo-stack--sm {
  gap: var(--ds-space-3);
}
.ds-demo-self-start {
  align-self: flex-start;
}
.ds-demo-max-sm {
  max-width: 360px;
}

/* Dark code sample block under each demo. */
.ds-demo-code {
  margin-top: var(--ds-space-8);
  padding: var(--ds-space-5);
  background: var(--ds-surface-dark);
  color: rgba(var(--ds-white-rgb), 0.92);
  border-radius: var(--ds-radius-md);
  overflow-x: auto;
  font-family: var(--ds-font-mono);
  font-size: var(--ds-text-body-sm);
}

/* Muted helper copy. */
.ds-demo-mute {
  color: var(--ds-ink-mute);
}
.ds-demo-caption {
  margin: 0;
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
}
.ds-demo-note {
  margin: var(--ds-space-2) 0 0;
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
}

/* Demo card copy (titles/body text inside bare .ds-card demos). */
.ds-demo-card-title {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
  color: var(--ds-ink);
  margin: 0;
}
.ds-demo-card-title--sm {
  font-size: var(--ds-text-body);
}
.ds-demo-card-text {
  margin: 0;
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
}
.ds-demo-list {
  margin: 0;
  padding-left: var(--ds-space-5);
  color: var(--ds-ink-soft);
  font-size: var(--ds-text-body-sm);
  line-height: var(--ds-lh-prose);
}

/* Color swatches (palette section) + token chips (token reference). */
.ds-demo-swatch {
  height: 100px;
  border-radius: var(--ds-radius-md);
}
.ds-demo-swatch--short {
  height: 72px;
}
.ds-demo-swatch--tile {
  height: 60px;
  border-radius: var(--ds-radius-sm);
}
.ds-demo-swatch--bordered {
  border: 1px solid var(--ds-border);
}
.ds-demo-swatch-caption {
  padding-top: var(--ds-space-2);
}

.ds-demo-bg--blue {
  background: var(--ds-blue);
}
.ds-demo-bg--red {
  background: var(--ds-red);
}
.ds-demo-bg--purple {
  background: var(--ds-purple);
}
.ds-demo-bg--purple-light {
  background: var(--ds-purple-light);
}
.ds-demo-bg--ink {
  background: var(--ds-ink);
}
.ds-demo-bg--ink-soft {
  background: var(--ds-ink-soft);
}
.ds-demo-bg--ink-mute {
  background: var(--ds-ink-mute);
}
.ds-demo-bg--surface {
  background: var(--ds-surface);
}
.ds-demo-bg--surface-tint {
  background: var(--ds-surface-tint);
}
.ds-demo-bg--surface-muted {
  background: var(--ds-surface-muted);
}
.ds-demo-bg--surface-dark {
  background: var(--ds-surface-dark);
}
.ds-demo-bg--surface-dark-2 {
  background: var(--ds-surface-dark-2);
}
.ds-demo-bg--success {
  background: var(--ds-success);
}
.ds-demo-bg--success-bright {
  background: var(--ds-success-bright);
}
.ds-demo-bg--warn {
  background: var(--ds-warn);
}
.ds-demo-bg--danger {
  background: var(--ds-danger);
}
.ds-demo-bg--info {
  background: var(--ds-info);
}
.ds-demo-bg--success-tint {
  background: var(--ds-success-tint);
}
.ds-demo-bg--warn-tint {
  background: var(--ds-warn-tint);
}
.ds-demo-bg--danger-tint {
  background: var(--ds-danger-tint);
}
.ds-demo-bg--info-tint {
  background: var(--ds-info-tint);
}
.ds-demo-bg--gradient-brand {
  background: var(--ds-gradient-brand);
}
.ds-demo-bg--gradient-brand-soft {
  background: var(--ds-gradient-brand-soft);
}

.ds-demo-token {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  padding: var(--ds-space-2);
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-sm);
  font-size: var(--ds-text-caption);
  height: 100%;
}
.ds-demo-token--block {
  display: block;
  padding: var(--ds-space-3);
}
.ds-demo-token__swatch {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: var(--ds-radius-xs);
}
.ds-demo-border--subtle {
  border-color: var(--ds-border-subtle);
}
.ds-demo-border--base {
  border-color: var(--ds-border);
}
.ds-demo-border--strong {
  border-color: var(--ds-border-strong);
}
.ds-demo-font-display {
  font-family: var(--ds-font-display);
}
.ds-demo-font-mono {
  font-family: var(--ds-font-mono);
}

/* Typography specimens. */
.ds-demo-type {
  font-family: var(--ds-font-display);
  font-weight: var(--ds-fw-black);
  line-height: var(--ds-lh-tight);
  letter-spacing: var(--ds-tracking-tight);
  color: var(--ds-ink);
}
.ds-demo-type--hero-dramatic {
  font-size: var(--ds-text-hero-dramatic);
}
.ds-demo-type--hero-standard {
  font-size: var(--ds-text-hero-standard);
}
.ds-demo-type--section {
  font-size: var(--ds-text-section);
}
.ds-demo-type--subsection {
  font-size: var(--ds-text-subsection);
  font-weight: var(--ds-fw-bold);
}
.ds-demo-type--body {
  font-size: var(--ds-text-body);
  font-weight: var(--ds-fw-regular);
  line-height: var(--ds-lh-prose);
  letter-spacing: normal;
  color: var(--ds-ink-soft);
  max-width: 640px;
  margin: 0;
}
.ds-demo-type--caption {
  font-size: var(--ds-text-caption);
  font-weight: var(--ds-fw-regular);
  letter-spacing: normal;
  line-height: var(--ds-lh-base);
  color: var(--ds-ink-mute);
}
.ds-demo-mono {
  font-family: var(--ds-font-mono);
  font-size: var(--ds-text-body-sm);
  background: var(--ds-surface-tint);
  padding: var(--ds-space-2) var(--ds-space-3);
  border-radius: var(--ds-radius-sm);
  display: inline-block;
}

/* Clipped showcase frame for hero demos. The frame caps the height; the
   inner hero drops its viewport-height minimum so the centered content is
   actually visible inside the 320px window (fixes the empty dramatic-hero
   demo box). */
.ds-demo-frame {
  height: 320px;
  overflow: hidden;
  position: relative;
  border-radius: var(--ds-radius-md);
  border: 1px solid var(--ds-border-subtle);
}
.ds-demo-frame .ds-hero {
  height: 100%;
  min-height: 0;
  padding: var(--ds-space-12) var(--ds-space-8);
}
.ds-demo-frame .ds-hero__title {
  font-size: var(--ds-text-section);
}
.ds-demo-frame .ds-hero__lead {
  font-size: var(--ds-text-body-sm);
}

/* Surface-mode demo tiles. */
.ds-demo-surface {
  position: relative;
  overflow: hidden;
  border-radius: var(--ds-radius-md);
  min-height: 180px;
}
.ds-demo-surface .ds-section {
  padding: var(--ds-space-8);
  min-height: 180px;
}
.ds-demo-on-dark-title {
  margin: var(--ds-space-2) 0 0;
  color: var(--ds-white);
}
.ds-demo-on-dark-text {
  margin: var(--ds-space-1) 0 0;
  color: rgba(var(--ds-white-rgb), 0.7);
}

/* Dark context panel (on-dark button demos). */
.ds-demo-dark-panel {
  background: var(--ds-surface-dark);
  padding: var(--ds-space-6);
  border-radius: var(--ds-radius-md);
}

/* Dashed info callout (scroll probe, replay playground). */
.ds-demo-callout {
  margin-top: var(--ds-space-8);
  padding: var(--ds-space-5);
  background: var(--ds-surface-tint);
  border-radius: var(--ds-radius-md);
  border: 1px dashed var(--ds-border);
}

/* SVG decoration-pattern tiles. */
.ds-demo-pattern-tile {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border-subtle);
  border-radius: var(--ds-radius-md);
  padding: var(--ds-space-6);
  position: relative;
  min-height: 200px;
  overflow: hidden;
}
.ds-demo-pattern-tile--dark {
  background: var(--ds-surface-dark);
  border: 0;
}
.ds-demo-pattern-tile svg {
  position: absolute;
  inset: 0;
}
.ds-demo-pattern-label {
  position: relative;
  color: var(--ds-ink);
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-body-sm);
}
.ds-demo-pattern-label--on-dark {
  color: var(--ds-white);
}

/* Gradient hero strip in the palette section. */
.ds-demo-gradient-strip {
  height: 96px;
  border-radius: var(--ds-radius-md);
  background: var(--ds-gradient-brand);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ds-demo-gradient-strip code {
  color: var(--ds-white);
  background: rgba(var(--ds-black-rgb), 0.12);
  padding: var(--ds-space-1) var(--ds-space-3);
  border-radius: var(--ds-radius-xs);
}
.ds-demo-pill-on-dark {
  height: 40px;
  padding: 0 var(--ds-space-4);
  border-radius: var(--ds-radius-full);
  background: var(--ds-gradient-brand-on-dark);
  display: flex;
  align-items: center;
  color: var(--ds-ink);
  font-weight: var(--ds-fw-bold);
  font-size: var(--ds-text-caption);
}
.ds-demo-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Radius / shadow token tiles. */
.ds-demo-radius--xs {
  border-radius: var(--ds-radius-xs);
}
.ds-demo-radius--sm {
  border-radius: var(--ds-radius-sm);
}
.ds-demo-radius--md {
  border-radius: var(--ds-radius-md);
}
.ds-demo-radius--lg {
  border-radius: var(--ds-radius-lg);
}
.ds-demo-radius--full {
  border-radius: var(--ds-radius-full);
}
.ds-demo-shadow--sm {
  box-shadow: var(--ds-shadow-sm);
  border: 1px solid var(--ds-border-subtle);
}
.ds-demo-shadow--md {
  box-shadow: var(--ds-shadow-md);
}
.ds-demo-shadow--lg {
  box-shadow: var(--ds-shadow-lg);
}
.ds-demo-shadow--gradient {
  box-shadow: var(--ds-shadow-gradient);
}
.ds-demo-shadow--focus {
  box-shadow: var(--ds-shadow-focus);
}

/* Spacing token bars. */
.ds-demo-space-row {
  display: flex;
  align-items: center;
  gap: var(--ds-space-3);
  font-size: var(--ds-text-caption);
}
.ds-demo-space-row code {
  min-width: 120px;
}
.ds-demo-space-bar {
  background: var(--ds-blue);
  height: 12px;
}
.ds-demo-space-bar--1 {
  width: var(--ds-space-1);
}
.ds-demo-space-bar--2 {
  width: var(--ds-space-2);
}
.ds-demo-space-bar--3 {
  width: var(--ds-space-3);
}
.ds-demo-space-bar--4 {
  width: var(--ds-space-4);
}
.ds-demo-space-bar--5 {
  width: var(--ds-space-5);
}
.ds-demo-space-bar--6 {
  width: var(--ds-space-6);
}
.ds-demo-space-bar--8 {
  width: var(--ds-space-8);
}
.ds-demo-space-bar--10 {
  width: var(--ds-space-10);
}
.ds-demo-space-bar--12 {
  width: var(--ds-space-12);
}
.ds-demo-space-bar--16 {
  width: var(--ds-space-16);
}
.ds-demo-space-bar--20 {
  width: var(--ds-space-20);
}
.ds-demo-space-bar--24 {
  width: var(--ds-space-24);
}

/* Lead-card demo contact line (mirrors the in-card contact treatment). */
.ds-demo-contact {
  font-size: var(--ds-text-caption);
  color: var(--ds-ink-mute);
  margin-top: var(--ds-space-1);
}

/* Static modal showcase: the fixed-position overlay component renders inside
   a relative frame instead of covering the viewport. */
.ds-demo-modal {
  position: relative;
  min-height: 380px;
  border-radius: var(--ds-radius-md);
  overflow: hidden;
  border: 1px solid var(--ds-border-subtle);
}
.ds-demo-modal .ds-modal {
  position: absolute;
}

/* Static consent-banner showcase: neutralize the fixed positioning. */
.ds-demo-consent .ds-consent {
  position: static;
  margin: 0;
  max-width: 520px;
}

/* Static filter-bar showcase: the open popover panel renders in-flow under
   its toggle instead of absolutely overlapping the sections below. */
.ds-demo-filter .ds-filter-group__panel {
  position: static;
  margin-top: var(--ds-space-2);
  box-shadow: var(--ds-shadow-md);
}

/* Neutralizes sticky/viewport-bound positioning on embedded demos (e.g. the
   sticky ds-panel--sidebar). Same specificity as the component rules but
   defined later in the file, so the cascade resolves without !important. */
.ds-demo-static {
  position: static;
  max-height: none;
}

/* Static toast showcase: suppress the animation entry state. */
.ds-demo-toast-stack {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  max-width: 380px;
}
.ds-demo-toast-stack .ls-toast {
  opacity: 1;
  transform: none;
  position: static;
}

/* Skeleton-loader showcase lines (the product sizes them contextually). */
.ds-demo-skel-line {
  max-width: 320px;
  margin-bottom: var(--ds-space-2);
}
.ds-demo-skel-line--short {
  max-width: 200px;
}

/* Cross-reference links inside demo lists join the 44px touch floor; the
   negative margin keeps the list rhythm while the hit box grows. */
@media (max-width: 767px) {
  .ds-demo-list a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -12px;
  }
}

/* ============================================================================
 * Reduced-Motion (accessibility — honors the OS "reduce motion" preference)
 * Neutralizes the decorative keyframe loops (orbs, blobs, particles, beams)
 * and collapses transitions so users who request reduced motion get a still
 * experience. The JS motion layers already self-disable; this covers the
 * CSS-only decorative animations. The !important resets are exempt from the
 * design gates' budget (see tests/test_design_gates.py).
 * ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
 * Print-Styles (primarily for /app/billing/invoices/ rendering)
 * Hide decorative chrome, force high-contrast ink on white, full-width tables.
 * ========================================================================== */

@media print {
  /* Force reveal/stagger elements visible (IO/GSAP don't fire in print mode) */
  .ds-reveal,
  .ds-stagger-child,
  .ds-stagger-parent > *,
  .ds-reveal-gsap,
  .ds-stagger-child-gsap,
  [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    visibility: visible !important;
  }

  /* Kill all decorative chrome + motion */
  .ds-site-header,
  .ds-site-footer,
  .ds-site-header__progress,
  .ds-cta-band,
  .ds-hero__bg,
  .ds-hero-mockup,
  .ds-trust-strip,
  .ds-consent,
  .ds-sticky-cta,
  [data-motion],
  .ds-op-orb,
  .ds-op-pattern-dots,
  .ds-op-pattern-hexa,
  .ds-op-pattern-sparkle,
  .ds-hero-beam,
  .ds-hero-spot,
  .ds-hero-particles,
  .ds-hero-conic,
  .ds-hero-grid-pattern,
  .ds-orb {
    display: none !important;
  }

  /* Reset layout shell for print */
  body.ds-layout-shell,
  html {
    background: var(--ds-white) !important;
    color: var(--ds-black) !important;
    font-family: var(--ds-font-display);
  }

  main.ds-layout-shell__body {
    padding: 0 !important;
  }

  /* Full-width sections, no background */
  .ds-section,
  .ds-hero,
  .ds-hero--standard,
  .ds-hero--dramatic {
    background: none !important;
    padding: 0 !important;
    min-height: 0 !important;
    margin-top: 0 !important;
    display: block !important;
  }

  .ds-section__inner {
    max-width: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
  }

  /* Force dark text on any hero/dark-section */
  .ds-hero__title,
  .ds-hero__lead,
  .ds-section__title,
  .ds-section__lead,
  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  p,
  li,
  td,
  th {
    color: var(--ds-black) !important;
    background: transparent !important;
  }

  /* Kill shadows, hover-transforms */
  .ds-card,
  .ds-panel,
  .ds-button {
    box-shadow: none !important;
    transform: none !important;
  }

  /* Tables (especially invoices): full-width, bordered, no background stripes */
  .ds-compare-table,
  table,
  .ds-card--content table {
    width: 100% !important;
    border-collapse: collapse !important;
    box-shadow: none !important;
  }
  .ds-compare-table th,
  .ds-compare-table td,
  table th,
  table td {
    border: 1px solid var(--ds-ink) !important;
    padding: 6px 10px !important;
    background: none !important;
  }
  .ds-compare-table th,
  table th {
    background: var(--ds-surface-muted) !important;
    font-weight: var(--ds-fw-bold);
  }

  /* Buttons: hide action-buttons in print (download PDF, pay, etc.) */
  .ds-button--primary,
  .ds-button--danger,
  button[type="submit"] {
    display: none !important;
  }
  .ds-button--secondary,
  .ds-button--ghost {
    border: 1px solid var(--ds-ink) !important;
    color: var(--ds-black) !important;
    background: transparent !important;
  }

  /* Gradient text becomes solid ink in print */
  .ds-gradient-text,
  .ds-gradient-text--on-dark {
    background: none !important;
    -webkit-text-fill-color: var(--ds-black) !important;
    color: var(--ds-black) !important;
  }

  /* Badges: solid black-and-white for print */
  .ds-badge {
    border: 1px solid var(--ds-black) !important;
    background: var(--ds-white) !important;
    color: var(--ds-black) !important;
  }

  /* Avoid page-break inside cards and table rows */
  .ds-card,
  tr,
  .ds-empty-state {
    page-break-inside: avoid;
  }

  /* Section-breaks: allow natural flow */
  .ds-section {
    page-break-before: auto;
    page-break-after: auto;
  }

  /* Print-only: show URLs after links for reference */
  a[href]:not([href^="#"])::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
    color: var(--ds-ink-soft);
  }

  /* Disable all animations and transitions */
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
