/*
 * Funnel4Leads - CI-Override.
 *
 * Überschreibt nur die Bootstrap-5-Custom-Properties aus
 * vendor/css/core.css (":root, [data-bs-theme=light]"). Muss NACH
 * core.css eingebunden werden, damit die Kaskade ohne !important
 * greift. Die Vendor-Datei selbst bleibt unangetastet (Update-Pfad).
 *
 * CI-Farben: #FF5A1F (Lead-Orange), #1C1F24 (Anthrazit),
 * #0B0D12 (Weltraum-Schwarz, dunkler Grund).
 */
:root {
  --bs-primary: #ff5a1f;
  --bs-primary-rgb: 255, 90, 31;
  --bs-primary-bg-subtle: #fff1ea;
  --bs-primary-border-subtle: #ffc4ad;
  /* Orange als Text auf Hell nur 3.2:1 - betonter Text bleibt Anthrazit. */
  --bs-primary-text-emphasis: #1c1f24;

  --bs-info: #1c1f24;
  --bs-info-rgb: 28, 31, 36;
}

/*
 * core.css definiert --bs-primary auch direkt auf [data-bs-theme=dark]
 * (eigene Farbpalette für den Dark-Modus). Das Semi-Dark-Menü trägt
 * dieses Attribut auf dem <aside>, daher überschreibt eine geerbte
 * :root-Regel dort NICHT - core.css's direkte Deklaration auf demselben
 * Element gewinnt sonst gegen die geerbte :root-Variable.
 */
[data-bs-theme=dark] {
  --bs-primary: #ff5a1f;
  --bs-primary-rgb: 255, 90, 31;
  --bs-primary-bg-subtle: #3a1d12;
  --bs-primary-border-subtle: #7a2e12;
  --bs-primary-text-emphasis: #ffb08f;

  --bs-info: #ff5a1f;
  --bs-info-rgb: 255, 90, 31;

  /* Sidebar-Hintergrund des Semi-Dark-Menüs. */
  --bs-menu-bg: #0b0d12;
  --bs-menu-bg-rgb: 11, 13, 18;
}

/* Sidebar-Logo wirkt bei fester Menü-Kopfhöhe sonst gequetscht. */
.app-brand-logo-img {
  padding-top: 6px;
}

/*
 * DataTables (Listenansichten): Pagination-Zeile hatte keinen
 * Abstand zum unteren Kartenrand, da die Tabelle direkt in
 * ".table-responsive" statt ".card-body" liegt. Zusätzlich: die
 * rohe, noch unstylisierte Tabelle wird bis zur Initialisierung
 * versteckt (kein Flackern bei großen Tabellen) und blendet danach
 * sanft ein.
 */
.dt-container > div:last-child {
  padding: 1rem 1.5rem 1.5rem;
}

.datatable-pending:not(.dataTable) {
  display: none;
}

.dt-container {
  animation: dt-fade-in .2s ease-out;
}

@keyframes dt-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/*
 * Public funnel fill-out flow (app/Modules/Funnel/Views/public/*).
 * Standalone pages, no admin layout - own light background + a single
 * centered column, wide enough to fit a 4-column choice-card grid.
 * Styled after common quiz-funnel conventions (big question, one-tap
 * single-choice, thin fixed progress line) rather than a boxed admin
 * card - this is the page a lead actually fills out, it should feel
 * like a product, not a settings form.
 */
.funnel-public-body {
  background-color: var(--bs-body-bg);
}

.funnel-wrapper {
  max-width: 46rem;
}

/* A step made of answer cards gets more room, so four cards keep their
   labels on one line instead of breaking mid-word. */
.funnel-wrapper--wide {
  max-width: 60rem;
}

.funnel-step-eyebrow {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--bs-body-color);
  opacity: .55;
  margin-bottom: .75rem;
}

.funnel-step-title {
  text-align: center;
  font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.25rem);
  font-weight: var(--funnel-heading-weight, 700);
  line-height: 1.25;
  /* The question needs room to breathe before the answers; a subtitle
     takes that role when there is one, so the gap moves down to it. */
  margin: 0 0 2.25rem;
}

.funnel-step-title:has(+ .funnel-step-subtitle) {
  margin-bottom: .5rem;
}

.funnel-step-subtitle {
  text-align: center;
  color: var(--bs-body-color);
  opacity: .65;
  margin-bottom: 2rem;
}

/* Fades the whole step in on load - a full page reload per step still
   benefits from this, it just softens the hand-off between pages. */
.funnel-card-enter {
  animation: funnel-fade-in .35s ease-out;
}

@keyframes funnel-fade-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/*
 * Card-style choice options (household size, roof shape, ...). The
 * radio/checkbox itself is visually hidden but stays in the tab order
 * and keyboard-operable - only its default appearance is removed, the
 * label (which wraps it) provides the click target and focus ring.
 */
.funnel-choice-card {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 11rem;
  height: 100%;
  cursor: pointer;
  border: 3px solid var(--funnel-card-border, transparent);
  border-radius: 1rem;
  /* Four cards share the 46rem form, so the label needs the room. */
  padding: 1.75rem 1rem;
  text-align: center;
  background-color: var(--bs-primary);
  color: var(--funnel-on-primary, #fff);
  transition: background-color .15s ease, transform .1s ease, box-shadow .15s ease;
}

.funnel-choice-card:hover {
  background-color: var(--funnel-primary-hover, var(--bs-primary));
}

.funnel-choice-card:active {
  transform: scale(.98);
}

.funnel-choice-card input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* Every card is already filled with the primary color, so "selected"
   can't be signalled by filling it - a contrasting ring plus the check
   badge in the corner carries that state instead. */
.funnel-choice-card:has(input:checked) {
  border-color: var(--funnel-on-primary, #fff);
  box-shadow: 0 0 0 3px var(--bs-primary);
}

.funnel-choice-card:has(input:focus-visible) {
  outline: 3px solid var(--bs-body-color);
  outline-offset: 3px;
}

/* --bs-icon-size drives the Tabler icon-font glyphs (.icon-base pins
   its own size to that variable and would otherwise ignore font-size),
   while font-size sizes the em-based uploaded SVGs - both need setting
   to keep the two icon kinds the same size. */
.funnel-choice-icon {
  display: block;
  font-size: 2.75rem;
  --bs-icon-size: 2.75rem;
  margin-bottom: .875rem;
  color: var(--funnel-card-icon, inherit);
}

/* Sized in em so it matches whichever ancestor's font-size sets the icon
   footprint (.funnel-choice-icon or .funnel-choice-row-icon) - one rule
   covers both the card and row/inline layouts. */
.funnel-choice-custom-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  object-fit: contain;
  vertical-align: -0.15em;
}

/* Only inside the filled cards - the row/inline layout keeps a light
   background, where the icons' own colors are already readable. */
.funnel-choice-card .funnel-choice-custom-icon {
  filter: var(--funnel-custom-icon-filter, none);
}

/* The card is a flex row, so its content would otherwise refuse to
   shrink below the longest word - on a phone "Einfamilienhaus" then ran
   out of the card and across the one next to it. */
.funnel-choice-card-body {
  display: block;
  min-width: 0;
  max-width: 100%;
}

.funnel-choice-label {
  display: block;
  font-weight: 500;
  /* Breaks a word only when it genuinely does not fit - no hyphens in
     the middle of "Gewerbe". */
  overflow-wrap: break-word;
}

.funnel-choice-card .funnel-choice-label {
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.3;
}

/* On a phone each card spans the whole width and reads as a row - icon
   beside the label - so four answers still fit on the screen. */
@media (max-width: 575.98px) {
  .funnel-choice-card {
    min-height: 4.75rem;
    padding: .875rem 1.125rem;
  }

  .funnel-choice-card-body {
    display: flex;
    align-items: center;
    gap: .875rem;
    width: 100%;
    text-align: left;
  }

  .funnel-choice-card .funnel-choice-icon {
    flex: none;
    margin-bottom: 0;
    font-size: 1.875rem;
    --bs-icon-size: 1.875rem;
  }

  .funnel-choice-card .funnel-choice-label {
    font-size: 1rem;
  }

  .funnel-choice-card-check {
    top: 50%;
    right: .875rem;
    transform: translateY(-50%) scale(.5);
  }

  .funnel-choice-card:has(input:checked) .funnel-choice-card-check {
    transform: translateY(-50%) scale(1);
  }
}

.funnel-choice-card-check {
  position: absolute;
  top: .625rem;
  right: .625rem;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--funnel-on-primary, #fff);
  color: var(--bs-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .875rem;
  opacity: 0;
  transform: scale(.5);
  transition: opacity .15s ease, transform .15s ease;
}

.funnel-choice-card:has(input:checked) .funnel-choice-card-check {
  opacity: 1;
  transform: scale(1);
}

/*
 * List-row choice options ("inline" style) - icon + label left, a
 * circular check indicator right. Used for both single- and
 * multi-select fields that don't need the visual weight of full cards.
 */
.funnel-choice-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  /* The column gap matches the form row's gutter so these rows land on
     exactly the same edges as the inputs above and below them; the row
     gap stays tighter, they belong to one field. */
  gap: .75rem 1.5rem;
}

/* A handful of short options (Herr / Frau / Divers) belong on one line -
   the auto-fit grid would drop the third onto a row of its own. */
.funnel-choice-list--row {
  grid-template-columns: repeat(var(--funnel-choice-columns, 3), 1fr);
}

@media (max-width: 575.98px) {
  .funnel-choice-list--row {
    grid-template-columns: 1fr;
  }
}

.funnel-choice-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: .75rem;
  cursor: pointer;
  /* Deliberately the metrics of a form control: these rows sit in the
     same grid as the text inputs (salutation next to first name), and a
     thicker border or a different height makes that one row look like a
     different kind of thing. */
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  padding: .4375rem 1rem;
  min-height: var(--funnel-control-height, 2.375rem);
  line-height: 1.375;
  transition: border-color .15s ease, background-color .15s ease;
}

.funnel-choice-row:has(input:checked) {
  /* One pixel more, taken off the padding, so selecting a row does not
     nudge the ones next to it. */
  border-width: 2px;
  padding: calc(.4375rem - 1px) calc(1rem - 1px);
}

.funnel-choice-row:hover {
  border-color: var(--bs-primary-border-subtle);
}

.funnel-choice-row input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.funnel-choice-row:has(input:checked) {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
}

.funnel-choice-row:has(input:focus-visible) {
  outline: 2px solid var(--bs-primary);
  outline-offset: 2px;
}

.funnel-choice-row-icon {
  font-size: 1.25rem;
  color: var(--bs-primary-text-emphasis);
  flex-shrink: 0;
}

.funnel-choice-row-label {
  font-weight: 500;
  flex-grow: 1;
}

.funnel-choice-row-indicator {
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  border: 2px solid var(--bs-border-color);
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
  font-size: .8125rem;
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}

.funnel-choice-row:has(input:checked) .funnel-choice-row-indicator {
  border-color: var(--bs-primary);
  background: var(--bs-primary);
  color: #fff;
}

/*
 * Step navigation. "Zurueck" and the forward button carry different
 * weight on purpose, but they are the same size - a small secondary
 * button next to a large primary one reads as a layout mistake rather
 * than as emphasis.
 */
.funnel-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 10.5rem;
  min-height: 3rem;
  padding: .625rem 1.75rem;
  font-size: 1rem;
  font-weight: 600;
  border-radius: var(--bs-border-radius);
}

/*
 * The last step is the one that costs the visitor something, so its
 * button gets weight - from width and a soft lift, not from height. A
 * tall block with a hard coloured shadow underneath reads as heavy
 * rather than as inviting, and the label here is a whole sentence
 * ("Jetzt unverbindlich Termin vereinbaren"), which needs room sideways.
 */
.funnel-btn--finish {
  min-width: 13rem;
  min-height: 3.25rem;
  padding: .75rem 2.5rem;
  font-size: 1rem;
  letter-spacing: .01em;
  white-space: nowrap;
  box-shadow: 0 .375rem 1rem -.5rem rgba(0, 0, 0, .35);
  box-shadow:
    0 .125rem .25rem -.125rem color-mix(in srgb, var(--bs-primary) 30%, transparent),
    0 .75rem 1.75rem -.75rem color-mix(in srgb, var(--bs-primary) 55%, transparent);
  transition: box-shadow .18s ease, transform .18s ease;
}

.funnel-btn--finish:hover {
  box-shadow:
    0 .125rem .25rem -.125rem color-mix(in srgb, var(--bs-primary) 35%, transparent),
    0 1rem 2rem -.75rem color-mix(in srgb, var(--bs-primary) 60%, transparent);
  transform: translateY(-2px);
}

.funnel-btn--finish:active {
  transform: translateY(0);
}

/* A sentence-long label has to wrap rather than push the button off the
   screen once there is no room to set it on one line. */
@media (max-width: 575.98px) {
  .funnel-btn--finish {
    white-space: normal;
    padding-inline: 1.25rem;
    font-size: .9375rem;
    line-height: 1.3;
  }
}

@media (max-width: 575.98px) {
  .funnel-btn {
    min-width: 0;
    flex: 1 1 0;
    padding-inline: 1rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .funnel-btn--finish:hover {
    transform: none;
  }
}

/* Slim, always-visible progress line pinned to the viewport bottom -
   stays in view without needing to scroll back up on long steps. */
.funnel-progress-fixed {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 4px;
  background: var(--bs-border-color);
  z-index: 1000;
}

.funnel-progress-fixed-bar {
  height: 100%;
  background: var(--bs-primary);
  transition: width .3s ease;
}

/*
 * Alternative progress indicators (funnel theme "progress_style"). Both
 * sit where the thin bar would, but as a small floating widget rather
 * than a full-width line - a battery charging up or a sun rising reads
 * as a metaphor, which only works if the shape is actually visible.
 */
.funnel-progress-widget {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: .625rem;
  padding: .5rem .875rem;
  border-radius: 999px;
  background: var(--bs-body-bg);
  box-shadow: 0 2px 12px rgb(0 0 0 / 12%);
  z-index: 1000;
}

.funnel-progress-widget__label {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--bs-body-color);
  font-variant-numeric: tabular-nums;
}

.funnel-battery {
  display: flex;
  align-items: center;
}

.funnel-battery__shell {
  width: 3rem;
  height: 1.375rem;
  border: 2px solid var(--bs-body-color);
  border-radius: .3125rem;
  padding: 2px;
  overflow: hidden;
}

.funnel-battery__fill {
  height: 100%;
  border-radius: .125rem;
  background: var(--bs-primary);
  transition: width .4s ease;
}

/* The nub on the positive terminal - purely decorative, but without it
   the shell reads as a plain rounded rectangle rather than a battery. */
.funnel-battery__cap {
  width: 3px;
  height: .625rem;
  margin-left: 1px;
  border-radius: 0 2px 2px 0;
  background: var(--bs-body-color);
}

.funnel-sun {
  width: 2.5rem;
  height: 2.5rem;
  display: block;
}

.funnel-sun__rays line {
  stroke: var(--bs-primary);
  stroke-width: 3;
  stroke-linecap: round;
}

.funnel-sun__disc {
  fill: var(--bs-border-color);
}

.funnel-sun__fill {
  fill: var(--bs-primary);
  transition: y .4s ease, height .4s ease;
}

/*
 * Appointment picker: the two stages (pick a day, then a time) are
 * labelled so the second row isn't mistaken for more dates, and times
 * that are already booked stay visible but clearly out of reach.
 */
.funnel-appointment-step-label {
  font-size: .8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--bs-body-color);
  opacity: .6;
  margin-bottom: .5rem;
}

.funnel-appointment-time-btn--taken {
  text-decoration: line-through;
  opacity: .45;
  cursor: not-allowed;
}

.funnel-appointment-chosen {
  font-weight: 600;
  color: var(--bs-primary-text-emphasis);
}

/*
 * Loading placeholders for the appointment picker. A sweeping highlight
 * rather than a spinner: the blocks already sit where the day and time
 * buttons will be, so the wait shows the shape of what is coming instead
 * of a symbol that says nothing about it.
 */
.funnel-skeleton-row {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: 1.5rem;
}

.funnel-skeleton {
  display: block;
  height: 2rem;
  border-radius: var(--bs-border-radius);
  background: linear-gradient(
    90deg,
    var(--bs-border-color) 25%,
    var(--bs-secondary-bg, #f2f2f3) 50%,
    var(--bs-border-color) 75%
  );
  background-size: 200% 100%;
  animation: funnel-skeleton-sweep 1.4s ease-in-out infinite;
}

.funnel-skeleton--date {
  width: 4.5rem;
  height: 4.25rem;
}

.funnel-skeleton--time {
  width: 4.5rem;
}

@keyframes funnel-skeleton-sweep {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

/* The real slots fade in so the swap from placeholder to buttons isn't
   an abrupt jump. */
.funnel-appointment-picker:not(.d-none) {
  animation: funnel-fade-in .3s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .funnel-skeleton {
    animation: none;
  }

  .funnel-appointment-picker:not(.d-none) {
    animation: none;
  }
}

/*
 * Appointment picker, laid out after the approved mockup: a horizontal
 * strip of days carrying an availability dot, then that day's times
 * split into parts of the day. Colors come from the funnel's own theme
 * variables throughout, so each customer's palette drives it.
 */
.funnel-daystrip-wrap {
  position: relative;
  min-width: 0;
  margin-bottom: 1rem;
}

.funnel-daystrip {
  display: flex;
  gap: .5rem;
  /* Without this the strip widens its column instead of scrolling, and the
     days spill past the card edge. */
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  /* overflow-x also clips vertically, so the hover lift and the focus ring
     need room inside the scroller. */
  padding: .25rem .125rem .5rem;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 2.5rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* The card at the edge fades out instead of being sliced off - only on
     the side that actually has more days behind it. */
  --funnel-daystrip-fade-start: 0px;
  --funnel-daystrip-fade-end: 0px;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--funnel-daystrip-fade-start), #000 calc(100% - var(--funnel-daystrip-fade-end)), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 var(--funnel-daystrip-fade-start), #000 calc(100% - var(--funnel-daystrip-fade-end)), transparent 100%);
}

.funnel-daystrip::-webkit-scrollbar {
  display: none;
}

.funnel-daystrip-wrap.has-prev .funnel-daystrip {
  --funnel-daystrip-fade-start: 2.5rem;
}

.funnel-daystrip-wrap.has-next .funnel-daystrip {
  --funnel-daystrip-fade-end: 2.5rem;
}

.funnel-daystrip-nav {
  position: absolute;
  top: calc(50% - .125rem);
  transform: translateY(-50%);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--bs-border-color);
  border-radius: 50%;
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}

.funnel-daystrip-nav:hover {
  border-color: var(--bs-primary);
  color: var(--bs-primary);
}

.funnel-daystrip-nav:focus-visible {
  outline: 3px solid var(--bs-body-color);
  outline-offset: 2px;
}

.funnel-daystrip-nav--prev {
  left: 0;
}

.funnel-daystrip-nav--next {
  right: 0;
}

.funnel-day {
  flex: none;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .25rem;
  width: 4.5rem;
  padding: .75rem 0 .625rem;
  border: 2px solid var(--bs-border-color);
  border-radius: .875rem;
  background: var(--bs-body-bg);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, transform .12s ease;
}

.funnel-day:hover:not(:disabled) {
  border-color: var(--bs-primary);
  transform: translateY(-2px);
}

.funnel-day:focus-visible {
  outline: 3px solid var(--bs-body-color);
  outline-offset: 2px;
}

.funnel-day.is-selected {
  background: var(--bs-primary);
  border-color: var(--bs-primary);
  color: var(--funnel-on-primary, #fff);
}

.funnel-day:disabled {
  cursor: not-allowed;
  opacity: .45;
}

.funnel-day__dow {
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .7;
}

.funnel-day__num {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.1;
}

.funnel-day__dot {
  width: .375rem;
  height: .375rem;
  border-radius: 50%;
  background: var(--bs-primary);
}

.funnel-day__dot.is-tight {
  background: #e9a13b;
}

.funnel-day__dot.is-full {
  background: var(--bs-border-color);
}

/* On the selected day the dot would otherwise disappear into the filled
   background, so it switches to the contrasting foreground. */
.funnel-day.is-selected .funnel-day__dot {
  background: var(--funnel-on-primary, #fff);
  opacity: .8;
}

.funnel-appointment-dayhead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.funnel-appointment-dayname {
  font-weight: 600;
  font-size: 1.0625rem;
}

.funnel-appointment-daycount {
  font-size: .8125rem;
  color: var(--bs-body-color);
  opacity: .6;
}

.funnel-slotgroup {
  margin-bottom: 1.25rem;
  animation: funnel-fade-in .25s ease-out;
}

.funnel-slotgroup__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .5rem;
}

.funnel-slotgroup__name {
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .55;
}

.funnel-slotgroup__note {
  font-size: .75rem;
  opacity: .4;
}

.funnel-slotgroup__list {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

.funnel-slot {
  padding: .625rem 1rem;
  border: 2px solid var(--bs-border-color);
  border-radius: 999px;
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  font-size: .9375rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, transform .12s ease;
}

.funnel-slot:hover:not(:disabled) {
  border-color: var(--bs-primary);
  transform: translateY(-1px);
}

.funnel-slot:focus-visible {
  outline: 3px solid var(--bs-body-color);
  outline-offset: 2px;
}

.funnel-slot.is-selected {
  background: var(--bs-primary);
  border-color: var(--bs-primary);
  color: var(--funnel-on-primary, #fff);
}

@media (prefers-reduced-motion: reduce) {
  .funnel-day,
  .funnel-slot,
  .funnel-slotgroup {
    transition: none;
    animation: none;
  }

  .funnel-day:hover:not(:disabled),
  .funnel-slot:hover:not(:disabled) {
    transform: none;
  }
}

/*
 * Structure canvas - the funnel as connected nodes, the way a branching
 * flow actually looks. Positions are inline styles written by the editor;
 * everything here is only appearance.
 */
.funnel-canvas {
  position: relative;
  overflow: auto;
  min-height: 32rem;
  /* 8-point grid throughout (CD 6.4), and a recessed ground so the nodes
     read as cards lying on it rather than as boxes drawn into it. */
  padding: 24px;
  /* A cool, slightly deeper ground: the cards on it are tinted warm, and
     two surfaces of the same lightness would not separate. */
  background-color: var(--funnel-canvas-bg, #E9ECF1);
  background-image: radial-gradient(circle, var(--bs-border-color) 1px, transparent 1px);
  background-size: 24px 24px;
  user-select: none;
}

[data-bs-theme="dark"] .funnel-canvas {
  --funnel-canvas-bg: #04091A;
}

/* On dark the tint comes from the same green, laid over anthracite -
   green 050 itself belongs to light grounds only. */
[data-bs-theme="dark"] .funnel-node {
  --funnel-node-bg: #121A2C;
  --funnel-node-head-bg: #18243A;
  --funnel-node-border: #263352;
}

.funnel-canvas.is-linking {
  cursor: crosshair;
}

.funnel-canvas__wires {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.wire {
  fill: none;
  stroke-width: 2;
}

.wire--default {
  stroke: var(--bs-border-color);
  stroke-dasharray: 5 4;
}

.wire--set {
  stroke: var(--bs-primary);
}

.wire--live {
  stroke: var(--bs-primary);
  stroke-dasharray: 4 3;
}

/* Each node is a card: same surface, border and corner as every other
   card in the backend, so the canvas belongs to the same system. The
   shadow is justified here - these really do lie over the canvas, which
   is the only case the manual allows one for (CD 6.3). */
.funnel-node {
  position: absolute;
  width: 16rem;
  border: 1px solid var(--funnel-node-border, var(--bs-border-color));
  border-radius: var(--webe-radius, 2px);
  /* Signal green 050, which the manual lists for exactly this - calm
     background surfaces (CD 4.3). White cards on a light canvas did not
     separate from it. */
  background: var(--funnel-node-bg, var(--webe-signal-050, #F7FAE0));
  box-shadow: 0 1px 2px rgba(14, 19, 34, .08), 0 6px 16px -8px rgba(14, 19, 34, .22);
  cursor: grab;
  transition: box-shadow .18s ease, border-color .18s ease;
}

.funnel-node:hover {
  border-color: var(--bs-primary);
}

.funnel-node.is-dragging {
  cursor: grabbing;
  box-shadow: 0 2px 4px rgba(14, 19, 34, .1), 0 16px 32px -12px rgba(14, 19, 34, .35);
  border-color: var(--bs-primary);
  z-index: 3;
}

.funnel-node--start,
.funnel-node--end {
  width: 12rem;
  padding: 16px;
  text-align: center;
}

.funnel-node--start {
  cursor: default;
}

.funnel-node--redirect {
  text-align: left;
}

/* A card header, tinted just enough to separate the question from its
   answers without drawing another line. */
.funnel-node__head {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 16px;
  /* One step deeper than the body, still inside the 050-200 range the
     manual allows for quiet surfaces. */
  background: var(--funnel-node-head-bg, color-mix(in srgb, var(--webe-signal, #FF5A1F) 10%, #ffffff));
  border-bottom: 1px solid var(--funnel-node-border, var(--bs-border-color));
}

/* The step number sits on Lead-Orange, so it is set in anthracite -
   text on orange is always anthracite in the brand book. */
.funnel-node__step {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--bs-primary);
  color: var(--webe-anthrazit, #1C1F24);
  font-size: .75rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}

.funnel-node__title {
  font-weight: 600;
  font-size: .8125rem;
  line-height: 1.3;
}

.funnel-node__hint {
  margin: .5rem 0 0;
  font-size: .6875rem;
  color: var(--bs-body-color);
  opacity: .6;
}

.funnel-node__body {
  padding: 8px 0;
}

.funnel-node__row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 16px;
  font-size: .8125rem;
}

/* An answer that leads somewhere of its own is marked by a green bar at
   the edge - the signal bar from the logo, doing the job it does
   elsewhere (CD 6.2) - rather than by green lettering, which on a light
   card would be the one text colour the manual forbids. */
.funnel-node__row.is-branched::before {
  content: '';
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 3px;
  background: var(--bs-primary);
}

.funnel-node__row.is-branched {
  font-weight: 500;
}

.funnel-node__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The connection points. Deliberately larger than they look, so grabbing
   one does not require precision aiming. */
.funnel-node__port {
  position: absolute;
  width: .75rem;
  height: .75rem;
  border: 2px solid var(--bs-primary);
  border-radius: 50%;
  background: var(--bs-body-bg);
}

.funnel-node__port::after {
  content: '';
  position: absolute;
  inset: -.5rem;
}

.funnel-node__port--out {
  right: -.4375rem;
  top: 50%;
  transform: translateY(-50%);
  cursor: crosshair;
}

.funnel-node__port--in {
  left: -.4375rem;
  top: 1.5rem;
}

.funnel-node--start .funnel-node__port--out,
.funnel-node--end .funnel-node__port--in {
  top: 50%;
  transform: translateY(-50%);
}

.funnel-node__port--out:hover {
  background: var(--bs-primary);
}

.funnel-node__foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 8px 16px;
  border-top: 1px solid var(--funnel-node-border, var(--bs-border-color));
}

.funnel-node__action {
  border: 0;
  background: none;
  padding: .125rem .25rem;
  color: var(--bs-body-color);
  opacity: .55;
  line-height: 1;
}

.funnel-node__action:hover {
  opacity: 1;
  color: var(--bs-primary);
}

@media (prefers-reduced-motion: reduce) {
  .funnel-node {
    transition: none;
  }
}

/*
 * The header's search. It takes the room between the logo and the avatar
 * rather than a fixed width - people search for e-mail addresses and
 * street names here, and a short box hides what they typed.
 */
.navbar-search {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 38rem;
}

.navbar-search .input-group {
  flex-wrap: nowrap;
}

.navbar-search .form-control:focus {
  box-shadow: none;
}

/* The magnifier and the field read as one control, so the border belongs
   around the pair rather than between them. */
.navbar-search .input-group:focus-within {
  border-radius: var(--bs-border-radius);
  box-shadow: 0 0 0 .125rem color-mix(in srgb, var(--bs-primary) 35%, transparent);
}

@media (max-width: 575.98px) {
  .navbar-search {
    max-width: none;
  }
}

/* Number field as a slider: the chosen value large above the track,
   the ends of the scale small below it. */
.funnel-slider {
  padding: 1.25rem 1.25rem 1rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg, .5rem);
  background: var(--bs-paper-bg, #fff);
}

.funnel-slider__value {
  display: block;
  margin-bottom: 1.25rem;
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--bs-primary);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.funnel-slider__track,
.funnel-slider__scale {
  display: none;
}

.funnel-slider.is-ready .funnel-slider__track {
  display: block;
  margin: 0 .75rem;
}

.funnel-slider.is-ready .funnel-slider__scale {
  display: flex;
  justify-content: space-between;
  margin-top: .875rem;
  font-size: .8125rem;
  color: var(--bs-secondary-color);
}

.funnel-slider .noUi-target {
  height: .5rem;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--bs-primary) 18%, var(--bs-border-color));
  box-shadow: none;
}

.funnel-slider .noUi-connect {
  background: var(--bs-primary);
}

.funnel-slider .noUi-horizontal .noUi-handle,
.funnel-slider .noUi-handle {
  top: -.6875rem;
  right: -.9375rem;
  width: 1.875rem;
  height: 1.875rem;
  border: 3px solid var(--bs-primary);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 .125rem .5rem rgba(0, 0, 0, .2);
  cursor: grab;
}

.funnel-slider .noUi-handle::before,
.funnel-slider .noUi-handle::after {
  display: none;
}

.funnel-slider .noUi-handle:active {
  cursor: grabbing;
}

.funnel-slider .noUi-handle:focus-visible {
  outline: 3px solid var(--bs-body-color);
  outline-offset: 2px;
}

/* Subheading between groups of fields in a longer form ("Kontakt",
   "Adresse"): a quiet title on a hairline, with room above it. */
.funnel-section-heading {
  margin-top: 1rem;
}

.row > .funnel-section-heading:first-child {
  margin-top: 0;
}

.funnel-section-heading__title {
  margin: 0;
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--bs-border-color);
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--bs-heading-color, inherit);
}
