/* ==========================================================================
   KHEWEUL — COUCHE RESPONSIVE GLOBALE
   --------------------------------------------------------------------------
   Ce fichier corrige, en un seul endroit, les défauts de responsivité qui
   touchaient toutes les pages : images sans borne, champs qui déclenchaient
   le zoom iOS, tableaux transformés en cartes sans libellés, barre de
   navigation basse masquée par l'indicateur d'accueil iPhone, cibles
   tactiles trop petites, décors géants peints sur mobile.

   ÉCHELLE DE POINTS DE RUPTURE (à reprendre dans les nouveaux fichiers)
       xs   <=  479.98px   téléphone étroit
       sm   <=  575.98px   téléphone
       md   <=  767.98px   grand téléphone / petite tablette portrait
       lg   <=  991.98px   tablette  (= bascule sidebar hors-écran)
       xl   <= 1199.98px   petit portable
   Les fichiers existants mélangent 767/768, 991/991.98/992, 575/576...
   Les valeurs en .98 évitent la zone morte d'un pixel entre max-width:768px
   et min-width:768px, où les deux règles s'appliquaient simultanément.

   ORDRE DE CHARGEMENT : chargé en dernier dans <head> (header.tpl). Les CSS
   par page (remdi.css, email_board.css, products_myproducts.css...) sont
   déclarés à l'intérieur des templates, donc APRÈS celui-ci : les correctifs
   qui doivent battre une règle de page portent !important, les autres non,
   pour que la page garde la main quand elle a déjà traité le cas.
   ========================================================================== */


/* ==========================================================================
   1. FONDATIONS
   ========================================================================== */

html {
    /* Empêche Safari iOS d'agrandir arbitrairement le texte en paysage. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* Les identifiants sans espace — noms de domaine, valeurs DNS, clés API,
   références de facture — étaient la première cause de débordement latéral.
   body{overflow-x:hidden} les rognait au lieu de les afficher. */
body {
    overflow-wrap: break-word;
}

/* Aucune feuille du thème (ni le thème parent twenty-one) ne bornait les
   médias : une image plus large que son conteneur élargissait la page. */
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
    max-width: 100%;
}

img,
video {
    height: auto;
}

/* Éléments de grille et colonnes Bootstrap : min-width:auto est la valeur par
   défaut d'un enfant de grille/flex, elle interdit de descendre sous la
   largeur du contenu. Un long libellé poussait donc toute la grille. */
.row > [class*="col-"],
[class*="-grid"] > *,
[class*="grid-"] > * {
    min-width: 0;
}

/* Contenus préformatés : enregistrements DNS, extraits de configuration. */
pre,
code,
kbd,
samp {
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}


/* ==========================================================================
   2. TYPOGRAPHIE FLUIDE
   Titres dimensionnés en dur sans repli mobile : 3.5rem = 56px sur un écran
   de 360px. clamp() les rend proportionnels sans toucher au rendu desktop.
   ========================================================================== */

.hero-title {
    font-size: clamp(1.9rem, 6vw, 3.5rem) !important;
}

.kw-vps-hero h1,
.hst-hero-title,
.dr-hero-title,
.kw2-hero h1 {
    font-size: clamp(1.65rem, 5.2vw, 2.5rem);
}

.kw-vps-price-amount,
.kw-combo-visual .combo-price .new-price {
    font-size: clamp(1.6rem, 5vw, 2.5rem);
}

.kw-empty-icon,
.kw-bp-shield-icon,
.dr-tld-emoji,
.kw-ssl-cta-icon-wrap {
    font-size: clamp(1.75rem, 5vw, 2.75rem);
}

@media (max-width: 767.98px) {
    /* Repli générique : sans !important, une règle de page reste prioritaire
       si elle a déjà traité le cas. */
    h1 { font-size: clamp(1.55rem, 6vw, 2.2rem); }
    h2 { font-size: clamp(1.3rem, 5vw, 1.75rem); }
    h3 { font-size: clamp(1.15rem, 4.2vw, 1.4rem); }
}


/* ==========================================================================
   3. FORMULAIRES — SUPPRESSION DU ZOOM AUTOMATIQUE iOS
   Safari iOS zoome à la mise au point sur tout champ dont la police est
   inférieure à 16px, et ne dézoome jamais : la page reste décalée. Plusieurs
   champs du thème étaient à 0.875rem / 0.92rem.
   ========================================================================== */

@media (max-width: 767.98px) {

    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]),
    select,
    textarea,
    .form-control,
    .kw-input,
    .kw-field,
    .kwrem-input,
    .kw-search-input {
        font-size: 16px !important;
    }

    /* Les champs restent pleine largeur : plus de rangée qui déborde. */
    .form-control,
    .custom-select,
    .kw-input,
    .kw-field {
        max-width: 100%;
    }

    /* Les groupes champ + bouton passent en colonne plutôt que d'écraser le
       champ à quelques pixels. Classe à poser au cas par cas. */
    .input-group.kw-stack-sm {
        flex-direction: column;
    }
    .input-group.kw-stack-sm > .form-control,
    .input-group.kw-stack-sm > .input-group-append,
    .input-group.kw-stack-sm > .input-group-append > .btn {
        width: 100%;
        border-radius: 8px;
    }
}


/* ==========================================================================
   4. CIBLES TACTILES
   Recommandation WCAG 2.2 (critère 2.5.8) et guides iOS/Android : 44x44px
   minimum. Restreint au pointeur grossier pour ne rien changer à la souris.
   ========================================================================== */

@media (hover: none) and (pointer: coarse) and (max-width: 991.98px) {

    .btn,
    a.btn,
    button.btn,
    [role="button"],
    input[type="submit"],
    input[type="button"],
    .kw-act-btn,
    .kw-filter-btn,
    .kw-btn,
    .kwrem-bouton,
    .kw-app-menu-item > a,
    .kw-submenu-list a {
        min-height: 44px;
    }

    /* Boutons purement iconiques : il leur manquait aussi la largeur. */
    .kw-more-btn,
    .kw-theme-toggle,
    .kw-sidebar-toggle,
    .kw-sidebar-close,
    .navbar-toggler,
    .kw-notifications-btn,
    .close {
        min-width: 44px;
        min-height: 44px;
    }

    /* Cases et boutons radio : la boîte visuelle reste petite, c'est la zone
       cliquable du libellé associé qui est agrandie. */
    .form-check-label,
    .kwrem-bascule {
        min-height: 32px;
        padding-top: 4px;
        padding-bottom: 4px;
    }

    /* Exceptions : contrôles volontairement compacts, dans un champ ou une
       cellule, qu'un min-height de 44px déformerait. */
    .kw-badge,
    .kw-status-pill,
    .input-group-append .btn.kw-inline-btn,
    td .btn-xs {
        min-height: 0;
    }
}


/* ==========================================================================
   5. ENCOCHES ET INDICATEUR D'ACCUEIL (iPhone X et suivants)
   Aucune règle env(safe-area-inset-*) n'existait : la barre de navigation
   basse de l'espace client passait sous la barre d'accueil, ses libellés
   étaient illisibles et le dernier onglet difficile à atteindre.
   ========================================================================== */

.kw-mobile-nav {
    height: auto;
    min-height: 64px;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    padding-left: max(10px, env(safe-area-inset-left, 0px));
    padding-right: max(10px, env(safe-area-inset-right, 0px));
}

@media (max-width: 991.98px) {
    /* Le contenu doit dégager la barre basse ET la zone sûre. */
    .kw-app-main {
        padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)) !important;
    }

    .kw-app-sidebar {
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }
}

/* Menu hors-écran des pages publiques : même traitement. */
#header #navbarNav.kw-offcanvas-open {
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
}


/* ==========================================================================
   6. TABLEAUX
   --------------------------------------------------------------------------
   6a. Le passage « tableau -> cartes » de custom.css sort le <thead> de
       l'écran (top:-9999px). Sans libellé reporté sur chaque cellule, les
       listes de l'espace client — factures, devis, tickets, téléchargements,
       contacts — devenaient des suites de valeurs nues : « 23/08/2026 »,
       « 12 500 F CFA », « Payée », sans savoir de quelle colonne il s'agit.
       kw-responsive.js pose l'attribut data-label sur chaque cellule à partir
       de l'en-tête correspondant ; la règle ci-dessous l'affiche.
   ========================================================================== */

@media (max-width: 768px) {

    .table-container table.table-list td[data-label]::before,
    table.kw-tbl-cards td[data-label]::before {
        content: attr(data-label);
        flex: 0 0 auto;
        margin-right: 14px;
        font-size: 0.7rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--kw-app-text-muted, #64748b);
        white-space: nowrap;
    }

    .dark-mode .table-container table.table-list td[data-label]::before,
    .dark-mode table.kw-tbl-cards td[data-label]::before {
        color: #94a3b8;
    }

    /* Colonnes d'actions et cases à cocher : leur en-tête est vide, on ne
       réserve pas de place pour un libellé inexistant. */
    .table-container table.table-list td[data-label=""]::before,
    table.kw-tbl-cards td[data-label=""]::before {
        content: none;
    }

    /* Une cellule vide dans une carte n'ajoute qu'un filet de séparation
       inutile (classe posée par kw-responsive.js). */
    .table-container table.table-list td.kw-cell-empty,
    table.kw-tbl-cards td.kw-cell-empty {
        display: none;
    }
}

/* --------------------------------------------------------------------------
   6b. Tableaux qui doivent rester des tableaux (zone DNS, comparatif SSL,
       relevés) : défilement horizontal explicite plutôt que rognage.
       .kw-scrollx est aussi la classe posée par kw-responsive.js autour des
       <table> qu'aucun conteneur défilable n'entourait.
   -------------------------------------------------------------------------- */

.kw-scrollx {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    max-width: 100%;
}

.kw-scrollx::-webkit-scrollbar {
    height: 6px;
}

.kw-scrollx::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.45);
    border-radius: 3px;
}

/* Indice visuel : un dégradé au bord droit tant qu'il reste à faire défiler.
   La classe est retirée par kw-responsive.js dès que la fin est atteinte. */
.kw-scrollx.kw-has-overflow {
    background-image: linear-gradient(to left, rgba(15, 23, 42, 0.10), rgba(15, 23, 42, 0));
    background-position: right center;
    background-repeat: no-repeat;
    background-size: 28px 100%;
    background-attachment: local;
}

.dark-mode .kw-scrollx.kw-has-overflow {
    background-image: linear-gradient(to left, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0));
}


/* ==========================================================================
   7. DÉCORS — HALOS ET ORBES
   Cercles flous de 400 à 700px de côté, dimensionnés en dur et sans repli.
   Sur un téléphone ils dépassent l'écran (rognés par overflow-x:hidden) et
   coûtent un flou plein écran à chaque peinture.
   ========================================================================== */

@media (max-width: 991.98px) {

    .kwh-orb,
    .kwh-orb-1,
    .kwh-orb-2,
    .kwh-orb-3,
    .kw-ssl-glow-1,
    .kw-ssl-glow-2,
    .kw-ssl-cta-glow,
    .kw-cpanel-cta-glow,
    .kw-vps-glow,
    .dr-hero::before,
    .dr-hero::after,
    .dr-hero-bg::after,
    .kw2-hero::before,
    .kw-combo::before,
    .kw-cta-box::before,
    .kw-login-brand::before {
        max-width: 70vw !important;
        max-height: 70vw !important;
    }
}

@media (max-width: 575.98px) {
    /* Sous 576px ces halos n'apportent plus rien de lisible. */
    .kwh-orb-2,
    .kwh-orb-3,
    .kw-ssl-glow-2,
    .dr-hero::after {
        display: none !important;
    }
}

/* Un utilisateur qui a demandé moins d'animation ne doit pas subir les
   dégradés animés ni les apparitions au défilement. Six fichiers seulement
   sur vingt honoraient cette préférence. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}


/* ==========================================================================
   8. MODALES ET MENUS DÉROULANTS
   ========================================================================== */

@media (max-width: 575.98px) {

    .modal-dialog {
        margin: 0.5rem;
        max-width: calc(100% - 1rem);
    }

    .modal-body {
        padding: 1rem;
    }

    .modal-header,
    .modal-footer {
        padding: 0.875rem 1rem;
    }

    /* Deux boutons côte à côte dans un pied de modale tombaient sous 100px
       de large : ils s'empilent. */
    .modal-footer {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }
    .modal-footer > .btn {
        width: 100%;
        margin: 0;
    }

    /* Menus déroulants ancrés à droite : bornés à la largeur de l'écran. */
    .dropdown-menu,
    .kw-dropdown {
        max-width: calc(100vw - 24px);
    }
    .kw-dropdown {
        min-width: 0;
    }
    .dropdown-menu-right {
        right: 0;
        left: auto;
    }
}

/* Le mégamenu du bandeau public n'a pas de sens en pointeur tactile étroit :
   c'est le menu hors-écran qui prend le relais. Sa largeur en dur (900px,
   850px, 750px) n'était bornée que par max-width:92vw. */
@media (max-width: 991.98px) {
    .megamenu-content {
        width: auto !important;
        max-width: 100% !important;
    }
}


/* ==========================================================================
   9. BARRES D'ONGLETS ET DE FILTRES
   Elles passent en défilement horizontal plutôt qu'en retour à la ligne au
   delà de trois éléments : la hauteur de l'en-tête reste stable.
   ========================================================================== */

@media (max-width: 575.98px) {

    .kw-products-filters,
    .kw-domains-filters,
    .kwh-tabs,
    .kw2-tabs,
    .hst-tld-pills {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 4px;
        scroll-snap-type: x proximity;
    }

    .kw-products-filters::-webkit-scrollbar,
    .kw-domains-filters::-webkit-scrollbar,
    .kwh-tabs::-webkit-scrollbar,
    .kw2-tabs::-webkit-scrollbar,
    .hst-tld-pills::-webkit-scrollbar {
        display: none;
    }

    .kw-products-filters > *,
    .kw-domains-filters > *,
    .kwh-tabs > *,
    .kw2-tabs > *,
    .hst-tld-pills > * {
        flex: 0 0 auto;
        scroll-snap-align: start;
    }
}


/* ==========================================================================
   10. PAYSAGE COURT (téléphone tourné, 380 à 520px de hauteur)
   Les héros calés sur la hauteur de l'écran remplissaient tout le viewport
   sans laisser voir le contenu qui suit.
   ========================================================================== */

@media (orientation: landscape) and (max-height: 520px) {

    .kwh-hero,
    .kw-vps-hero,
    .dr-hero,
    .kw2-hero,
    .kw-ssl-hero,
    .kw-cpanel-hero,
    .hst-hero,
    .kheweul-hero-fullwidth {
        min-height: 0 !important;
        padding-top: 32px !important;
        padding-bottom: 32px !important;
    }

    /* La barre basse mange un tiers de la hauteur utile en paysage. */
    .kw-mobile-nav {
        min-height: 52px;
    }
    .kw-mobile-nav-item i {
        font-size: 1.05rem;
    }
    .kw-app-main {
        padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* Un menu hors-écran plus haut que l'écran doit défiler. */
    #header #navbarNav.kw-offcanvas-open,
    .kw-app-sidebar {
        overflow-y: auto;
    }
}


/* ==========================================================================
   11. TÉLÉPHONES ÉTROITS (<= 380px : Galaxy A0x, iPhone SE 1re génération,
   parc encore très présent au Sénégal)
   Les grilles en minmax(280px, 1fr) n'y tiennent plus une fois la gouttière
   du conteneur retirée : 360 - 2x16 = 328px de large utile.
   ========================================================================== */

@media (max-width: 380px) {

    .kw-app-content-container,
    .container,
    .container-fluid {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    [class*="-grid"],
    [class*="grid-"] {
        gap: 10px;
    }

    /* Les grilles bornées à 280px/300px repassent sous la largeur utile. */
    .kw-fluid-grid-3,
    .kw-service-grid,
    .kw-vps-cards-grid,
    .kw2-grid,
    .kw-eb-tiles {
        grid-template-columns: 1fr !important;
    }

    .kw-mobile-nav-item span {
        font-size: 0.58rem;
    }
}


/* ==========================================================================
   12. PALIERS MANQUANTS RELEVÉS À L'AUDIT
   ========================================================================== */

/* .kw-service-grid n'avait de repli qu'à 767px : entre 768 et 991px elle
   gardait trois colonnes, soit des cartes de ~230px sur une tablette. */
@media (min-width: 768px) and (max-width: 991.98px) {
    .kw-service-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Zone DNS et comparatif SSL : leur largeur minimale (720px / 800px) est
   volontaire, on garantit seulement que le conteneur défile réellement. */
.kwdns-cadre,
.kw-ssl-compare-wrap {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}


/* ==========================================================================
   13. RANGÉES « TITRE À GAUCHE / ACTIONS À DROITE »
   Ces conteneurs sont en display:flex sans flex-wrap et sans repli mobile :
   sous 576px le titre et son bouton se disputent la largeur et l'un des deux
   finit écrasé. flex-wrap ne change rien tant que la place suffit, il ne
   s'applique qu'au moment où la rangée déborderait.
   (Liste établie par recensement des règles flex sans wrap ni requête de
   média ; les barres à hauteur fixe — topbar, sidebar — en sont exclues.)
   ========================================================================== */

@media (max-width: 575.98px) {

    .kw-dash-card-header,
    .kw-panel-header,
    .kw-pm-card-header,
    .kw-pm-modal-header,
    .kw-pm-modal-footer,
    .kw-pm-alert,
    .kw-pm-security-notice,
    .kw-af-notice,
    .kw-notifications-header,
    .kw-form-label-row,
    .kw-pref-header,
    .kw-pref-footer,
    .login-dropdown-footer,
    .kh-section-head,
    .kw-domain-actions,
    .kw-eb-alert,
    .kw-mail-alert,
    .kw-ssl-panel-header,
    .kw-ssl-panel-card-header,
    .kw-ssl-card-header-row {
        flex-wrap: wrap;
        gap: 10px;
    }

    /* Une barre d'actions qui se replie doit occuper toute la largeur, sinon
       les boutons se retrouvent alignés à droite sur une ligne à eux. */
    .kw-domain-actions > *,
    .kw-pm-modal-footer > .btn {
        flex: 1 1 auto;
    }
}


/* ==========================================================================
   14. IMPRESSION — factures et devis
   ========================================================================== */

@media print {

    .kw-app-sidebar,
    .kw-app-topbar,
    .kw-mobile-nav,
    .kw-sidebar-backdrop,
    #header,
    #footer,
    .topbar-modern,
    .no-print {
        display: none !important;
    }

    .kw-app-main,
    .kw-app-layout,
    .kw-app-content-container {
        margin: 0 !important;
        padding: 0 !important;
        width: 100% !important;
    }

    body {
        background: #ffffff !important;
        color: #000000 !important;
    }
}


/* ==========================================================================
   15. BULLE WHATSAPP ET BARRE DE NAVIGATION BASSE
   Les pages de l'espace client affichent une barre fixe en bas d'écran
   (.kw-mobile-nav, 64px + zone sûre). La bulle WhatsApp est ancrée à 14px du
   bas : elle recouvrait le dernier onglet, « Profil », qui devenait
   inatteignable. Elle est relevée au-dessus de la barre — uniquement sur ces
   pages, repérées par la classe kw-has-bottom-nav posée sur <body>.
   ========================================================================== */

@media (max-width: 991.98px) {

    body.kw-has-bottom-nav .kw-whatsapp-float {
        bottom: calc(64px + 14px + env(safe-area-inset-bottom, 0px));
    }

    /* Le bouton de thème se cale au-dessus de la bulle, pas sous elle. */
    body.kw-has-bottom-nav #kw-theme-toggle {
        bottom: calc(64px + 72px + env(safe-area-inset-bottom, 0px));
    }
}

@media (max-width: 380px) {

    body.kw-has-bottom-nav .kw-whatsapp-float {
        bottom: calc(64px + 10px + env(safe-area-inset-bottom, 0px));
    }

    body.kw-has-bottom-nav #kw-theme-toggle {
        bottom: calc(64px + 64px + env(safe-area-inset-bottom, 0px));
    }
}

/* En paysage court la barre basse est plus fine (52px, cf. §10). */
@media (orientation: landscape) and (max-height: 520px) {

    body.kw-has-bottom-nav .kw-whatsapp-float {
        bottom: calc(52px + 10px + env(safe-area-inset-bottom, 0px));
    }

    body.kw-has-bottom-nav #kw-theme-toggle {
        bottom: calc(52px + 58px + env(safe-area-inset-bottom, 0px));
    }
}
