///
/// This file regroups the CSS rules made to fix/extend bootstrap in frontend
/// ==============================================================================

// Extend bootstrap to create background and text utilities for gray colors too
// Note: the card-body rule below needs those grays utilities to be defined
// before so that the related o-bg-color text-muted rules work.
@each $color, $value in $grays {
    @include bg-variant(".bg-#{$color}", $value);
    @include text-emphasis-variant(".text-#{$color}", $value);
}

// Restore text-X from BS4 that use text-emphasis-variant
@each $color, $value in $theme-colors {
    @include text-emphasis-variant(".text-#{$color}", $value);
}

// Cards

.card {
    // Bootstrap sets up background-color using `var(--card-bg)` but forces a
    // color using `var(--body-color)`. It relies on `var(--card-color)` being
    // used on the card-body... but there does not seem to be a valid reason
    // to force the body one on the card above. Given the fact that `card-color`
    // is actually null by default, we end up with an inconsistent body-color
    // forced on the card whatever the value of `card-bg`. In the website case,
    // we often set up `card-bg` to inherit by default, which means the text
    // color would only work if the card was over the body background color.
    // By forcing `card-color` we enforce something consistent and controllable,
    // which by default will result as the card text color just following the
    // parent environment one (as `card-color` is null by default). We assume
    // that if `card-bg` is set, then `card-color` should be too.

    // Note: doing `color: var(--card-color)` would prevent overriding
    // --body-color in the card context (which is a bit weird) but it does not
    // work: it would override the color given by bg-xxx in the .card.bg-xxx
    // case, which is not what we want.
    --body-color: var(--card-color);
}
:where(.card:not([data-vxml])) .card-body:not(.card[data-vxml] .card-body) {
    // BS4 colored cards do not have a very popular design. This will reset them
    // to a BS3-like one: only the header and footer are colored and the body
    // will use the color of a default card background with a light opacity.
    // Limitation: bg-* utilities cannot be used on card-body elements anymore.
    // Note: these rules need grays utilities to be defined before so that the
    // related o-bg-color text-muted rules work. Since backend and fronted
    // generate these classes differently, this pseudo-class is called in the
    // respective 'bootstrap_review_x' file immediately after gray classes
    // generation.
    @include o-bg-color(rgba($card-bg, $o-card-body-bg-opacity), $important: false);

    &:first-child {
        @include border-top-radius($card-inner-border-radius);
    }
    &:last-child {
        @include border-bottom-radius($card-inner-border-radius);
    }
}

// Generating bootstrap color buttons was disabled (see import_bootstrap.scss).
// We do it ourself here with a tweak: we introduce btn-fill-* (working as the
// normal btn-* classes (in opposition to btn-outline-* classes). We then map
// the btn-* classes to either btn-fill-* or btn-outline-* classes depending on
// the configuration. We also allow to define a border-color different than the
// background color.
$o-btn-bg-colors: () !default;
$o-btn-border-colors: () !default;
@each $color, $value in $theme-colors {
    $-bg-color: map-get($o-btn-bg-colors, $color) or $value;
    $-border-color: map-get($o-btn-border-colors, $color) or $-bg-color;
    .btn-fill-#{$color} {
        @include button-variant($-bg-color, $-border-color);
    }
}
@each $color, $value in $theme-colors {
    $-bg-color: map-get($o-btn-bg-colors, $color) or $value;
    $-border-color: increase-contrast(map-get($o-btn-border-colors, $color) or $-bg-color, $body-bg);
    .btn-outline-#{$color} {
        @include button-outline-variant($-border-color);
    }
}
$o-btn-flat-defaults: () !default;
$o-btn-outline-defaults: () !default;
$o-btn-outline-border-width-defaults: () !default;
@each $color, $value in $theme-colors {
    .btn-#{$color} {
        @if index($o-btn-outline-defaults, $color) {
            @extend .btn-outline-#{$color};
            border-width: map-get($o-btn-outline-border-width-defaults, $color);
        } @else {
            @extend .btn-fill-#{$color};
            @if index($o-btn-flat-defaults, $color) {
                // TODO In master: move definition to web_editor
                @extend .btn.flat !optional;
            }
        }
    }
}

// Highlight '.btn-group's active buttons
.btn-group .btn-light.active {
    box-shadow: inset 0 0 0 $border-width $component-active-bg;
    border-color: transparent;
    background-color: mix($component-active-bg, $light, 10%);
}

// Compensate navbar brand padding if no visible border
@if alpha($navbar-dark-toggler-border-color) < 0.001 {
    .navbar-dark .navbar-toggler {
        padding-left: 0;
        padding-right: 0;
    }
}
@if alpha($navbar-light-toggler-border-color) < 0.001 {
    .navbar-light .navbar-toggler {
        padding-left: 0;
        padding-right: 0;
    }
}

// Review bootstrap navbar to work with different nav styles
$o-navbar-nav-pills-link-padding-x: $nav-link-padding-x !default;
$o-navbar-nav-pills-link-border-radius: $nav-pills-border-radius !default;
.navbar-nav.nav-pills .nav-link {
    // The rules is needed so that the padding is not reset to 0 in mobile.
    // Also use default nav-link paddings instead of navbar ones.
    padding-right: $o-navbar-nav-pills-link-padding-x;
    padding-left: $o-navbar-nav-pills-link-padding-x;

    @if $o-navbar-nav-pills-link-border-radius != $nav-pills-border-radius {
        @include border-radius($o-navbar-nav-pills-link-border-radius);
    }
}

.carousel-control-next .visually-hidden {
    left: 50%; // Avoid horizontal scrollbar in Chrome
}

// Pagination
.pagination {
    font-variant-numeric: tabular-nums;
}

// Ensure circle pagination
.page-link {
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
    width: 2.5em;
    aspect-ratio: 1 / 1;
}

// Ensure the readability of numbers when there are many (>3) and
// they overflow the circle.
.page-link.active, .active > .page-link {
    text-shadow: 0 0 .1em var(--pagination-active-bg);
}

// Show the page content behind the offcanvas < sm, fallback at 400px above.
.offcanvas {
    @include media-breakpoint-down(sm) {
        --Offcanvas-horizontal-width: calc(100vw - #{map-get($spacers, 5)});
    }
}

// Modal
.modal-content {
    // If the text color of the body (used for the text color in modals) is not
    // visible due to insufficient contrast with the modal background, we adjust
    // the text color in the modal using the following code. For example, if the
    // user sets a black background for its website and the text color of the
    // body is white, the text will not be visible on modals with a white
    // background.

    @if $modal-content-color == null {
        color: adjust-color-to-background($body-color, $modal-content-bg);

        // This prevents these elements from taking their colors from the body
        // inside a modal.
        // We need to exclude 'oe_structure' that are areas containing editable
        // snippets. Indeed, this code was added in a stable version, and we are
        // doing everything not to alter the content edited by users. For
        // example in Website, without this 'not', the 's_website_form' snippets
        // with a black background in modals and on websites with a black
        // background would have their input background changing from black to
        // white.
        // TODO: In Master, find a more consistent way to define the background
        // color of 's_website_form' snippet inputs inside a modal.
        &:where(:not(.oe_structure)) {
            @if ($input-bg == $body-bg) {
                .form-control {
                    background-color: $modal-content-bg;
                    color: color-contrast($modal-content-bg);
                }
            }
            @if ($form-select-bg == $body-bg) {
                .form-select {
                    background-color: $modal-content-bg;
                    color: color-contrast($modal-content-bg);;
                }
            }
            @if $form-check-input-bg == $body-bg {
                .form-check-input:not(:checked) {
                    background-color: $modal-content-bg;
                }
            }
        }
    }
    .text-muted {
        color: adjust-color-to-background($text-muted, $modal-content-bg, mute-color($color-contrast-light), mute-color($color-contrast-dark)) !important;
    }
}

// Popover
.popover {
    // The popover can have a different background color than that of the body.
    // Here, we adjust the text color of the popover in case the body color
    // (used by default for the text color of popovers) is not visible inside a
    // popover due to a lack of contrast (e.g. on a website with a dark
    // background).
    @if $popover-header-color == null {
        .popover-header {
            color: adjust-color-to-background($body-color, $popover-header-bg);
        }
    }
    @if $popover-body-color == $body-color {
        .popover-body {
            color: adjust-color-to-background($body-color, $popover-bg);
        }
    }
}

// Form
.form-check-input {
    // Without this line, the border of the checkboxes is not visible when the
    // body is dark. This is due to the fact that the borders are defined based
    // on the 'currentColor' of the inputs.
    color: inherit;
}
.form-control.bg-light {
    @include o-search-cancel-button(adjust-color-to-background($input-color, $light));

    color: adjust-color-to-background($input-color, $light);
}

// Default style inputs
input[type="search"] {
    @include o-search-cancel-button($input-color);
}

$-color-for-gray-200-bg: adjust-color-to-background($body-color, $gray-200);
// Input group text (e.g. Date time picker)
.input-group-text {
    // Adapt only if the variables have their default values.
    @if ($input-group-addon-bg == $gray-200) and ($input-group-addon-color == $body-color) {
        color: $-color-for-gray-200-bg;
    }
}
// File upload button
.form-control::file-selector-button {
    @if ($form-file-button-bg == $gray-200) and ($form-file-button-color == $body-color) {
        color: $-color-for-gray-200-bg;
    }
}

// offcanvas
.offcanvas {
    @if $offcanvas-color == null {
        color: adjust-color-to-background($body-color, $offcanvas-bg-color);

        @if $form-check-input-bg == $body-bg {
            .form-check-input:where(:not(:checked)) {
                background-color: $offcanvas-bg-color;
            }
        }
        @if $form-range-thumb-bg == $body-bg {
            .form-range {
                &::-webkit-slider-thumb {
                    &:where(:not(:active)) {
                        background-color: $offcanvas-bg-color;
                    }
                }
                &::-moz-range-thumb {
                    &:where(:not(:active)) {
                        background-color: $offcanvas-bg-color;
                    }
                }
            }
        }
    }
}

// Button within input-group (e.g., "search bar")
.input-group {
    .btn:first-child, .btn:last-child {
        @include border-radius($input-border-radius, 0);
    }
}

// Dropdown
.dropdown-menu {
    .text-muted {
        color: adjust-color-to-background($text-muted, $dropdown-bg, mute-color($color-contrast-light), mute-color($color-contrast-dark)) !important;
    }

    // Since we define the $dropdown-link-active-bg variable, we need to
    // redefine the .active state of the dropdown items to differentiate
    // an active class from the active state. This allows a discreet effect for
    // the active state while keeping an active navigation element prominent.
    .dropdown-item.active {
        --dropdown-link-active-bg: #{$component-active-bg};
        --dropdown-link-active-color: #{$component-active-color};
    }
}

// The following code adapts the style of disabled inputs to maintain color
// consistency and make them more recognizable.
.form-select {
    // This is necessary to achieve a consistent "border rendering behaviour"
    // across form-select and form-control when using semi-transparent
    // borders and a background color (eg. disabled inputs).
    // Otherwise, the color rendering of the semi-transparent border may be altered
    // (the color may be darker depending on the background color used).
    background-clip: padding-box;

    &:disabled:not([multiple]):where(:not([size]), [size="1"]) {
        background-image: str-replace($form-select-indicator, #{$form-select-indicator-color}, str-replace(#{$form-select-disabled-color}, "#", "%23"));
    }
}

.form-control {
    &:disabled, &[readonly] {
        color: $form-select-disabled-color;
    }
}

.form-check-input:disabled:not(:checked) {
    background-color: $input-disabled-bg;

    .form-switch & {
        background-image: escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-select-disabled-color}'/></svg>"));
    }
}

.form-range:disabled::-webkit-slider-thumb {
    border-color: $input-disabled-border-color;
}
