 html,
 body {
   height: 100%;
   scrollbar-gutter: stable;
 }

 body {
   display: flex;
   flex-direction: column;
 }

 main {
   flex: 1;
   background: var(--bs-tertiary-bg);
 }

 /* Charging-station/connector icons (chargingStation.html) are static
    black-line-art images on a transparent background, so they're invisible
    against a dark page. hue-rotate(180deg) alongside the invert keeps the
    small red accent in sockets/typeF.png roughly the right color instead of
    turning it cyan. */
 :root[data-bs-theme="dark"] img[src*="/media/icons/"],
 :root[data-bs-theme="dark"] img[src*="/media/sockets/"] {
   filter: invert(1) hue-rotate(180deg);
 }

 /* Light/dark logo variants (see partials/logo.html) - both are rendered,
    CSS picks the one matching the active theme. Not used when forceDarkLogo
    is set (logo.html then renders a single, always-dark <img> instead). */
 .logo-dark {
   display: none;
 }

 :root[data-bs-theme="dark"] .logo-light {
   display: none;
 }

 :root[data-bs-theme="dark"] .logo-dark {
   display: inline-block;
 }

 .hero {
   /* background-image: url('../media/lama_bg.jpg'); */
   background-repeat: no-repeat;
   background-position: center center;
   background-size: cover;
   min-height: 50vh;
   transition: min-height 0.3s ease;
 }

 .hero-fullscreen {
   min-height: 100vh;
 }

 .header-wrapper {
   z-index: 1001;
 }

 .header-abs {
   position: absolute;
   top: 0;
   left: 0;
   right: 0;
   width: 100%;
 }

 .header-rel {
   position: relative;
 }

 .header-abs a,
 .header-abs .nav-link {
   color: #fff !important;
   font-weight: 500;
   text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
   transition: all 0.2s ease;
 }

 .header-abs .nav-link:hover {
   background-color: rgba(255, 255, 255, 0.15) !important;
   color: #fff !important;
 }

 .header-abs .nav-link.active {
   background-color: rgba(255, 255, 255, 0.25) !important;
   color: #fff !important;
   font-weight: 600;
 }

 /* Absolute Footer for Fullscreen mode (landing page) - sits on top of the
    hero photo, not the page surface, so its text must always stay in the
    light/white style, regardless of the visitor's data-bs-theme selection. */
 .footer-abs,
 :root[data-bs-theme="dark"] .footer-abs {
   position: absolute;
   bottom: 0;
   left: 0;
   right: 0;
   width: 100%;
   z-index: 1001;
   color: #fff !important;
   text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
 }

 .footer-abs a,
 :root[data-bs-theme="dark"] .footer-abs a {
   color: #fff !important;
   font-weight: 500;
   transition: opacity 0.2s ease;
 }

 .footer-abs a:hover {
   opacity: 0.8;
   text-decoration: underline !important;
 }

 .footer-abs .text-spacer {
   color: rgba(255, 255, 255, 0.5) !important;
 }

 .footer-rel a {
   color: var(--bs-body-color);
 }

 /* Make sure the main content is at the top when in fullscreen */
 .fullscreen-layout main {
   padding: 0;
   background: transparent;
 }

 .hero .search-wrapper {
   backdrop-filter: blur(0px);
   width: 100%;
 }

 /* Sub-line link below the hero search box (see index.html). Always styled
    light + shadowed, like .header-abs/.footer-abs, since the hero can carry
    a background image regardless of the fullscreenHero feature flag. */
 .hero-sub-link,
 .hero-sub-link:hover {
   color: #fff;
   text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
 }

 .hero-sub-link:hover {
   text-decoration: underline !important;
 }

 /* When a tenant's hero background is too light/busy for white overlay text
    to stay legible (forceHighContrastLandingPage - see partials/logo.html,
    which already forces the dark logo variant for the same reason), flip
    the header/footer/hero-sub-link text to dark instead. Off by default -
    the light/white styling above still applies otherwise. */
 .high-contrast-hero .header-abs a,
 .high-contrast-hero .header-abs .nav-link {
   color: #000 !important;
   text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
 }

 .high-contrast-hero .header-abs .nav-link:hover {
   background-color: rgba(0, 0, 0, 0.1) !important;
   color: #000 !important;
 }

 .high-contrast-hero .header-abs .nav-link.active {
   background-color: rgba(0, 0, 0, 0.15) !important;
   color: #000 !important;
 }

 .high-contrast-hero .footer-abs,
 .high-contrast-hero:root[data-bs-theme="dark"] .footer-abs {
   color: #000 !important;
   text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
 }

 .high-contrast-hero .footer-abs a,
 .high-contrast-hero:root[data-bs-theme="dark"] .footer-abs a {
   color: #000 !important;
 }

 .high-contrast-hero .footer-abs .text-spacer {
   color: rgba(0, 0, 0, 0.5) !important;
 }

 .high-contrast-hero .hero-sub-link,
 .high-contrast-hero .hero-sub-link:hover {
   color: #000 !important;
   text-shadow: 0 1px 2px rgba(255, 255, 255, 0.6);
 }

 /* The dropdown-menu popup (language switcher) is a solid, non-transparent
    panel once opened - not an overlay on the hero image/color like the nav
    links above it - so it shouldn't inherit the forced white/black overlay
    text color. Let Bootstrap's own theme-scoped colors take over instead;
    the header.html partial sets data-bs-theme="dark" on this dropdown-menu
    when forceHighContrastLandingPage is set, so it always renders with a
    dark background + light text there regardless of the visitor's light/dark
    toggle choice. */
 .header-abs .dropdown-menu a {
   color: var(--bs-dropdown-link-color) !important;
   text-shadow: none !important;
 }

 .search-wrapper-centered {
   display: flex;
   justify-content: center;
   align-items: center;
   height: 100%;
 }

 .feature-hero {
   min-height: 300px;
   background-size: cover;
   background-position: center;
   position: relative;
   border-radius: .5rem;
   overflow: hidden;
 }

 .feature-hero .overlay {
   position: absolute;
   inset: 0;
   background: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.55) 60%, rgba(0, 0, 0, 0.65) 100%);
 }

 .feature-hero h3 {
   position: absolute;
   bottom: 1rem;
   left: 1rem;
   right: 1rem;
   margin: 0;
   color: #fff;
   font-weight: 600;
 }

 .background-faq {
   background: #ebfffd;
 }

 :root[data-bs-theme="dark"] .background-faq {
   background: #0d2b29;
 }

 /* Place this AFTER the Bootstrap CSS. Built on --brand-color (see the
    :root block below) rather than fixed hex values, so it automatically
    tracks both the tenant's configured brand color and the light/dark
    theme toggle - --brand-color itself already resolves to
    brandColorLight/brandColorDark per data-bs-theme (see layout.html). */
 .btn-brand {
   --bs-btn-color: #fff;
   --bs-btn-bg: var(--brand-color);
   --bs-btn-border-color: var(--brand-color);
   --bs-btn-hover-color: #fff;
   --bs-btn-hover-bg: color-mix(in srgb, var(--brand-color) 85%, black);
   --bs-btn-hover-border-color: color-mix(in srgb, var(--brand-color) 85%, black);
   --bs-btn-active-color: #fff;
   --bs-btn-active-bg: color-mix(in srgb, var(--brand-color) 75%, black);
   --bs-btn-active-border-color: color-mix(in srgb, var(--brand-color) 75%, black);
   --bs-btn-disabled-color: #fff;
   --bs-btn-disabled-bg: color-mix(in srgb, var(--brand-color) 60%, var(--bs-tertiary-bg));
   --bs-btn-disabled-border-color: color-mix(in srgb, var(--brand-color) 60%, var(--bs-tertiary-bg));
 }

 .form-section-divider {
   border-color: var(--bs-gray-500) !important;
 }

 /* Light gray active pill styling */
 .nav-pills-light {
   --bs-nav-pills-link-active-bg: #e9ecef;
   /* light gray */
   --bs-nav-pills-link-active-color: #212529;
   /* dark text */
 }

 /* Optional: tone for non-active links and hover */
 .nav-pills-light .nav-link {
   color: #6c757d;
 }

 .nav-pills-light .nav-link:hover {
   background-color: #f8f9fa;
 }

 .text-spacer {
   color: var(--bs-gray-300) !important;
 }

 /* Remove focus glow from search input */
 #evseId:focus {
   box-shadow: none !important;
   border-color: #dee2e6;
 }

 /* #button-search / #button-qrcode use Bootstrap's static .btn-light variant
    (they sit on top of the hero photo, not the page surface, so they can't
    just use --bs-body-bg like the rest of the form) - .btn-light itself
    never changes with data-bs-theme, so it needs an explicit dark override
    here. */
 :root[data-bs-theme="dark"] #button-search,
 :root[data-bs-theme="dark"] #button-qrcode {
   background-color: var(--bs-tertiary-bg);
   border-color: var(--bs-border-color);
   color: var(--bs-body-color);
 }

 :root[data-bs-theme="dark"] #button-search:hover,
 :root[data-bs-theme="dark"] #button-qrcode:hover {
   background-color: var(--bs-secondary-bg);
 }

 /* Branding accent used by the selection cards below. Overridden per-tenant
    via an inline :root declaration in layout.html, driven by the
    "brandColor" environment config value. */
 :root {
   --brand-color: #3b82f6;
   --brand-color-tint: color-mix(in srgb, var(--brand-color) 8%, white);
   --brand-color-border-tint: color-mix(in srgb, var(--brand-color) 25%, white);
 }

 /* Selectable checkbox card, e.g. "Benötigen Sie eine Rechnung?" on the
    payment page: icon, text and checkbox in a single vertically centered
    row. */
 .checkbox-card {
   display: flex;
   align-items: center;
   gap: 1rem;
   border: 2px solid var(--brand-color-border-tint);
   border-radius: 1rem;
   padding: 1rem;
   cursor: pointer;
   background-color: var(--bs-body-bg);
   transition: border-color .15s ease, background-color .15s ease;
 }

 .checkbox-card:hover {
   border-color: var(--brand-color);
 }

 .checkbox-card:has(.checkbox-card-input:checked) {
   border-color: var(--brand-color);
   background-color: var(--brand-color-tint);
 }

 .checkbox-card-icon {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   flex-shrink: 0;
   width: 2.5rem;
   height: 2.5rem;
   border-radius: 0.75rem;
   color: var(--brand-color);
   font-size: 1.25rem;
 }

 .checkbox-card-text {
   display: flex;
   flex-direction: column;
   flex-grow: 1;
   min-width: 0;
 }

 .checkbox-card-title {
   color: var(--brand-color);
   font-weight: 700;
 }

 .checkbox-card-description {
   color: var(--bs-secondary-color);
   font-size: 0.875rem;
 }

 .checkbox-card-input {
   appearance: none;
   -webkit-appearance: none;
   flex-shrink: 0;
   width: 1.375rem;
   height: 1.375rem;
   margin: 0;
   border: 2px solid var(--brand-color);
   border-radius: 50%;
   background-color: var(--bs-body-bg);
   cursor: pointer;
 }

 .checkbox-card-input:checked {
   background-color: var(--brand-color);
   background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath d='M13.485 1.929a1 1 0 0 1 0 1.414l-7.07 7.071a1 1 0 0 1-1.415 0L2.515 7.929a1 1 0 1 1 1.414-1.414l1.768 1.768 6.364-6.364a1 1 0 0 1 1.414 0Z'/%3E%3C/svg%3E");
   background-repeat: no-repeat;
   background-position: center;
   background-size: 0.75rem;
 }

 /* Selectable radio card, e.g. tariff selection on the payment page: title
    + description on one line on the left, filled radio dot on the right. */
 .radio-card {
   border: 2px solid var(--bs-border-color);
   border-radius: 0.75rem;
   padding: 1rem 1.25rem;
   cursor: pointer;
   background-color: var(--bs-body-bg);
   transition: border-color .15s ease;
 }

 .radio-card:hover {
   border-color: var(--brand-color);
 }

 .radio-card:has(.radio-card-input:checked) {
   border-color: var(--brand-color);
   background-color: var(--brand-color-tint);
 }

 /* Tariffs with a future startDateTime aren't selectable yet - the input
    is disabled server-side, this just conveys it visually. */
 .radio-card-disabled {
   cursor: not-allowed;
   background-color: var(--bs-tertiary-bg);
 }

 .radio-card-disabled:hover {
   border-color: var(--bs-border-color);
 }

 .radio-card-disabled .radio-card-title,
 .radio-card-disabled .radio-card-description,
 .radio-card-disabled .radio-card-availability {
   color: var(--bs-secondary-color);
 }

 .radio-card-icon {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   flex-shrink: 0;
   width: 2.5rem;
   height: 2.5rem;
   border-radius: 0.75rem;
   color: var(--brand-color);
   font-size: 1.25rem;
 }

 .radio-card-disabled .radio-card-icon {
   color: var(--bs-secondary-color);
 }

 .radio-card-label {
   min-width: 0;
   flex-grow: 1;
 }

 .radio-card-title {
   font-weight: 700;
   color: var(--bs-body-color);
   flex-grow: 1;
 }

 .radio-card-description {
   color: var(--bs-secondary-color);
   font-size: 0.875rem;
   margin-left: 0.5rem;
 }

 .radio-card-availability {
   display: block;
   color: var(--bs-secondary-color);
   font-size: 0.75rem;
   margin-top: 0.125rem;
 }

 .radio-card-input {
   appearance: none;
   -webkit-appearance: none;
   width: 1.5rem;
   height: 1.5rem;
   margin: 0;
   flex-shrink: 0;
   border: 2px solid var(--bs-border-color);
   border-radius: 50%;
   background-color: var(--bs-body-bg);
   cursor: pointer;
 }

 .radio-card-input:disabled {
   cursor: not-allowed;
   background-color: var(--bs-tertiary-bg);
   border-color: var(--bs-border-color);
 }

 .radio-card-input:checked {
   border-color: var(--brand-color);
   background-color: var(--brand-color);
   box-shadow: inset 0 0 0 4px #fff;
 }

 /* Stripe payment method selector (Kreditkarte / SEPA-Lastschrift / giropay)
    reuses the .radio-card look; the label just needs a bit less padding
    since it only holds a title + radio dot, no description. */
 .stripe-method-tab {
   padding: 0.75rem 1.25rem;
 }

 .stripe-method-panel.d-none {
   display: none;
 }

 /* Stripe Card/IBAN Element container - the element itself renders an
    iframe with no chrome, so the border/padding/focus ring is styled on
    the wrapper. Stretched to the full width of the form column. */
 .stripe-card-element {
   width: 100%;
   padding: 0.75rem 0.875rem;
   border: 1px solid var(--bs-border-color);
   border-radius: 0.5rem;
   background-color: var(--bs-body-bg);
   transition: border-color .15s ease, box-shadow .15s ease;
 }

 .stripe-card-element-focused {
   border-color: var(--brand-color);
   box-shadow: 0 0 0 3px var(--brand-color-tint);
 }

 /* Bootstrap tables put a border under every row (including the last one) -
    drop it so the table doesn't end with a stray line, e.g. the evses list
    on the station page. */
 .table > tbody > tr:last-child > td,
 .table > tbody > tr:last-child > th {
   border-bottom: none;
 }

 #snackbar {
   visibility: hidden;
   min-width: 250px;
   background-color: var(--bs-emphasis-color);
   color: var(--bs-body-bg);
   text-align: center;
   border-radius: 0.5rem;
   padding: 16px;
   position: fixed;
   z-index: 1080;
   left: 50%;
   transform: translateX(-50%);
   bottom: 30px;
 }

 #snackbar.show {
   visibility: visible;
   -webkit-animation: snackbar-fadein 0.5s, snackbar-fadeout 0.5s 2.5s;
   animation: snackbar-fadein 0.5s, snackbar-fadeout 0.5s 2.5s;
 }

 @-webkit-keyframes snackbar-fadein {
   from { bottom: 0; opacity: 0; }
   to { bottom: 30px; opacity: 1; }
 }

 @keyframes snackbar-fadein {
   from { bottom: 0; opacity: 0; }
   to { bottom: 30px; opacity: 1; }
 }

 @-webkit-keyframes snackbar-fadeout {
   from { bottom: 30px; opacity: 1; }
   to { bottom: 0; opacity: 0; }
 }

 @keyframes snackbar-fadeout {
   from { bottom: 30px; opacity: 1; }
   to { bottom: 0; opacity: 0; }
 }

 /* Card grid used by the session status pages (payment + free-to-charge) to
    display live transaction metrics (status, duration, energy, SoC, cost). */
 .stat-card {
   height: 100%;
   padding: 1.25rem 1rem;
   border: 1px solid var(--bs-border-color);
   border-radius: 0.75rem;
   background-color: var(--bs-body-bg);
   text-align: center;
 }

 .stat-card-icon {
   display: block;
   margin-bottom: 0.5rem;
   font-size: 1.75rem;
   color: var(--brand-color);
 }

 .stat-card-label {
   font-size: 0.8rem;
   color: var(--bs-secondary-color);
 }

 .stat-card-value {
   margin-top: 0.15rem;
   font-size: 1.15rem;
   font-weight: 600;
 }

 /* Charge point info card (EVSE-ID/address/connector) stacks its value lines
    instead of the single-line metric cards below it. */
 .stat-card-charge-point .stat-card-value {
   display: flex;
   flex-direction: column;
   gap: 0.15rem;
   font-size: 1rem;
 }

 /* 1-5 star rating input on the feedback form. Radio inputs are rendered in
    reverse (5..1) order in the markup and laid out right-to-left, so the
    ~ sibling selector below can light up a clicked star and every star before
    it (i.e. visually after it, since the row is reversed). */
 .star-rating {
   display: inline-flex;
   flex-direction: row-reverse;
   justify-content: center;
   gap: 0.25rem;
 }

 .star-rating input {
   position: absolute;
   opacity: 0;
   pointer-events: none;
 }

 .star-rating label {
   font-size: 2rem;
   line-height: 1;
   color: var(--bs-border-color);
   cursor: pointer;
 }

 .star-rating input:checked ~ label,
 .star-rating label:hover,
 .star-rating label:hover ~ label {
   color: var(--brand-color);
 }

 .tariff-chart-current {
   color: var(--bs-body-color);
 }

 .tariff-chart-secondary {
   min-height: 1.2em;
 }

 .tariff-chart-wrapper {
   overflow: hidden;
   border-radius: 0.5rem;
 }

 .tariff-chart {
   position: relative;
   height: 5rem;
   background-color: var(--bs-tertiary-bg);
 }

 /* No gap between bars: their widths are percentages of the chart's total
    width and must sum to exactly 100% so the (also percentage-based)
    .tariff-chart-now line lines up with them at any viewport width - a fixed
    px gap would eat a different proportion of the total width depending on
    the container's actual pixel size, drifting the bars out of sync with the
    line as the page is resized. */
 .tariff-chart-bar {
   flex: 0 0 auto;
   background-color: var(--brand-color);
   min-height: 2px;
   box-shadow: inset -1px 0 0 var(--bs-tertiary-bg);
   transition: opacity .2s ease;
   cursor: pointer;
 }

 .tariff-chart-bar:last-child {
   box-shadow: none;
 }

 .tariff-chart-bar-muted {
   opacity: 0.3;
 }

 .tariff-chart-bar-active {
   opacity: 1;
 }

 .tariff-chart-bar-static {
   background-color: var(--bs-secondary-color);
 }

 /* outline (not border) so the selection indicator is purely decorative and
    doesn't add to the bar's box size - bar widths must keep summing to exactly
    100% of the chart's width for the now-line to stay aligned with them (see
    the no-gap comment above). outline-offset pulls it inward so it doesn't
    bleed into neighboring bars. Wins over the base bar's muted opacity via the
    compound selector's higher specificity. */
 .tariff-chart-bar.tariff-chart-bar-selected {
   opacity: 1;
   outline: 2px solid var(--bs-body-bg);
   outline-offset: -2px;
 }

 .tariff-chart-day-boundary {
   position: absolute;
   top: 0;
   bottom: 0;
   width: 0;
   border-left: 1px dashed var(--bs-secondary-color);
   opacity: 0.6;
   pointer-events: none;
 }

 .tariff-chart-now {
   position: absolute;
   top: 0;
   bottom: 0;
   width: 2px;
   margin-left: -1px;
   background-color: var(--bs-danger, #dc3545);
   pointer-events: none;
 }

 .tariff-chart-now::before {
   content: "";
   position: absolute;
   top: -4px;
   left: 50%;
   transform: translateX(-50%);
   width: 6px;
   height: 6px;
   border-radius: 50%;
   background-color: var(--bs-danger, #dc3545);
 }

 .tariff-chart-axis {
   min-height: 1.2em;
 }

 .tariff-chart-axis-start {
   position: absolute;
   left: 0;
 }

 .tariff-chart-axis-end {
   position: absolute;
   right: 0;
 }

 .tariff-chart-axis-boundary {
   position: absolute;
   white-space: nowrap;
 }