@charset "UTF-8";
/*!
 * Melonslab — Blesta client theme
 *
 * Loaded after application.min.css, so it restyles Bootstrap 4.6 and Blesta's
 * own components rather than replacing them. Every core, module and plugin
 * template keeps working because the markup is untouched.
 *
 * Palette, type and shape are taken from the Melonslab Nuxt site so the panel
 * and the marketing site read as one product.
 */

/* ---------------------------------------------------------------- fonts --
   Self-hosted to match the marketing site, which avoids Google's CDN at
   runtime. Latin and latin-ext only. */
@font-face {
    font-family: "DM Sans";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("../webfonts/dmsans-300-700-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "DM Sans";
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url("../webfonts/dmsans-300-700-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../webfonts/poppins-600-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../webfonts/poppins-600-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../webfonts/poppins-700-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Poppins";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../webfonts/poppins-700-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------- tokens --
   Warm neutrals, no blue tint. That is the defining choice of the brand and
   the reason the old theme read as "just blue". */
:root {
    --ml-canvas: #f5f5f7;
    --ml-surface: #ffffff;
    --ml-surface-2: #e9e9ee;
    --ml-surface-3: #f5f5f7;
    --ml-border: #dcdce1;
    --ml-border-strong: #c0c0c8;
    --ml-hairline: #e9e9ee;
    --ml-row-hover: #f5f5f7;
    --ml-expand-bg: #f5f5f7;
    --ml-scrim: rgb(245 245 247 / 0.72);

    --ml-ink: #0a0a0c;
    --ml-body: #55555f;
    --ml-muted: #6f6f7a;
    --ml-faint: #94949e;

    /* Melon Red: identity, links, active state. Never a conversion button. */
    --ml-accent: #e02440;
    --ml-accent-hover: #bc1732;
    /* Filled surfaces keep one red in both themes. Only text lightens in dark,
       so these two are deliberately not redeclared below. */
    --ml-accent-solid: #e02440;
    --ml-accent-solid-hover: #bc1732;
    --ml-accent-ring: #f44c5c;
    --ml-accent-bg: #fff1f2;
    --ml-accent-line: #ffc9cd;
    --ml-accent-text: #bc1732;

    /* Melon Green: every action that spends money or creates something. */
    --ml-go: #036c30;
    --ml-go-hover: #045526;
    --ml-go-active: #033f1d;

    --ml-ok: #06b84e;
    --ml-ok-bg: #d4fbe8;
    --ml-ok-line: #acf5d3;
    --ml-ok-text: #036c30;

    --ml-warn: #f59e0b;
    --ml-warn-bg: #ffedd5;
    --ml-warn-line: #fed7aa;
    --ml-warn-text: #c2410c;

    --ml-bad-bg: #fff1f2;
    --ml-bad-line: #ffc9cd;
    --ml-bad-text: #bc1732;

    --ml-info: #0ea5e9;
    --ml-info-bg: #e0f2fe;
    --ml-info-line: #bae6fd;
    --ml-info-text: #0369a1;

    --ml-r-sm: 6px;
    --ml-r: 8px;
    --ml-r-lg: 12px;
    --ml-r-xl: 16px;
    --ml-r-pill: 999px;

    --ml-grid-opacity: 0.04;
    --ml-shadow-sm: 0 1px 2px 0 rgb(10 10 12 / 0.05);
    --ml-shadow-lg: 0 10px 15px -3px rgb(10 10 12 / 0.1), 0 4px 6px -4px rgb(10 10 12 / 0.1);
    --ml-glow: rgb(244 76 92 / 0.09);

    --ml-sans: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    --ml-display: "Poppins", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    --ml-mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

    /* Bootstrap 4 declares its palette as :root custom properties that its own
       CSS never reads (0 uses of var() in application.css). The order plugin
       does read them, so retinting the three it uses fixes its borders, slider
       and helper text without touching Bootstrap. They point at --ml-* tokens,
       so they follow the theme automatically. */
    --light: var(--ml-border);
    --secondary: var(--ml-muted);
    --info: var(--ml-accent-ring);

    --ml-bar-h: 64px;
    --ml-shell: 1280px;
    --ml-pad: 24px;
}

html[data-theme="dark"] {
    --ml-canvas: #0a0a0c;
    --ml-surface: #141419;
    --ml-surface-2: #26262c;
    --ml-surface-3: #141419;
    --ml-border: #26262c;
    --ml-border-strong: #40404a;
    --ml-hairline: #26262c;
    --ml-row-hover: #1c1c22;
    --ml-expand-bg: rgb(255 255 255 / 0.02);
    --ml-scrim: rgb(10 10 12 / 0.72);

    --ml-ink: #f5f5f7;
    --ml-body: #94949e;
    --ml-muted: #94949e;
    --ml-faint: #6f6f7a;

    --ml-accent: #f76e7c;
    --ml-accent-hover: #ffa0a8;
    --ml-accent-bg: #470811;
    --ml-accent-line: #9c172f;
    --ml-accent-text: #ffa0a8;

    --ml-ok: #06b84e;
    --ml-ok-bg: #011a0c;
    --ml-ok-line: #045526;
    --ml-ok-text: #6deaaf;

    --ml-warn-bg: #431407;
    --ml-warn-line: #9a3412;
    --ml-warn-text: #fdba74;

    --ml-bad-bg: #470811;
    --ml-bad-line: #9c172f;
    --ml-bad-text: #ffa0a8;

    --ml-info-bg: #082f49;
    --ml-info-line: #075985;
    --ml-info-text: #7dd3fc;

    --ml-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.4);
    --ml-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.6), 0 4px 6px -4px rgb(0 0 0 / 0.5);
    --ml-glow: rgb(244 76 92 / 0.07);
    --ml-grid-opacity: 0.06;
}

/* ----------------------------------------------------------------- base -- */
html {
    background-color: var(--ml-canvas);
}

html,
body {
    font-size: 15px;
}

/* Keeps the footer at the bottom of the viewport on short pages. .ml-foot
   already carries margin-top:auto. */
body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}
main.ml-shell { flex: 1 0 auto; }

/* The canvas is set at html[data-theme] strength because Blesta's Custom CSS
   commonly carries per-route rules like `body.client-client_login-index
   { background-color: #fff }`, which outrank a bare `body` selector and would
   pin the page to one colour in both themes. */
html[data-theme] body {
    background-color: var(--ml-canvas);
}

body,
.panel .panel-heading .panel-title {
    background-color: var(--ml-canvas);
    color: var(--ml-body);
    font-family: var(--ml-sans);
    font-size: 0.9333rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6,
.panel .panel-body h4,
.card-header,
.modal-title,
.global_modal_title {
    font-family: var(--ml-display);
    font-weight: 600;
    color: var(--ml-ink);
    letter-spacing: -0.02em;
}

h1 { font-size: 1.875rem; font-weight: 700; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.0625rem; }
h5 { font-size: 0.9375rem; }

p { color: var(--ml-body); }
strong, b { font-weight: 600; color: var(--ml-ink); }
small { color: var(--ml-muted); }

a,
a:hover {
    color: var(--ml-accent);
}
a:hover {
    color: var(--ml-accent-hover);
    text-decoration: underline;
}

hr {
    border: 0;
    border-top: 1px solid var(--ml-border);
    margin: 1.25rem 0;
}

label {
    color: var(--ml-muted);
    font-size: 0.8125rem;
    font-weight: 500;
    margin-bottom: 0.375rem;
}

::selection {
    background-color: #f44c5c;
    color: #fff;
}

:focus-visible {
    outline: 2px solid var(--ml-accent-ring);
    outline-offset: 2px;
    border-radius: var(--ml-r-sm);
}

/* Machine data: addresses, identifiers, credentials, money. Read character by
   character and copied, so it gets a monospace face and tabular figures.
   Deliberately not applied to labels or prose. */
code, kbd, samp, pre,
.ml-mono {
    font-family: var(--ml-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.875em;
}
code, samp, pre { color: var(--ml-ink); background: transparent; }
kbd { background: var(--ml-surface-2); color: var(--ml-ink); border-radius: var(--ml-r-sm); }
caption { color: var(--ml-muted); }

.ml-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    padding: 0.75rem 1rem;
    background: var(--ml-surface);
    color: var(--ml-ink);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
}
.ml-skip:focus {
    left: 1rem;
    top: 1rem;
}

.ml-shell {
    width: 100%;
    max-width: var(--ml-shell);
    margin: 0 auto;
    padding: 0 var(--ml-pad);
}

main.ml-shell {
    padding-top: 1.75rem;
    padding-bottom: 4rem;
    min-height: 45vh;
}

main.ml-shell-auth {
    padding-top: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 82vh;
}

/* ----------------------------------------------------------------- bar --
   Sits on the canvas rather than a coloured band, so the page head's glow
   reads as one field behind both. */
.ml-bar {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--ml-canvas);
    background: color-mix(in srgb, var(--ml-canvas) 88%, transparent);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--ml-border);
}

.ml-bar-inner {
    max-width: var(--ml-shell);
    margin: 0 auto;
    padding: 0 var(--ml-pad);
    min-height: var(--ml-bar-h);
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.ml-logo {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    border-radius: var(--ml-r);
}
.ml-logo:hover { text-decoration: none; }
.ml-logo img {
    height: 30px;
    width: auto;
    display: block;
}
/* Suffix names the theme the artwork is for, not the ink it uses. */
html[data-theme="dark"] .ml-logo-light,
html[data-theme="dark"] .ml-pay-light { display: none; }
html:not([data-theme="dark"]) .ml-logo-dark,
html:not([data-theme="dark"]) .ml-pay-dark { display: none; }

.ml-nav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex: 1 1 auto;
    min-width: 0;
}

.ml-nav-list {
    display: flex;
    align-items: center;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
    min-width: 0;
}

/* The pill that carries primary navigation, borrowed from the site header.
   It must never scroll: overflow-x:auto computes overflow-y to auto as well,
   which clips the dropdowns that open inside it. It wraps instead. */
.ml-nav > .ml-nav-list:first-child {
    background: var(--ml-surface-2);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-pill);
    padding: 4px 6px;
    overflow: visible;
    flex-wrap: wrap;
}

.ml-nav-end {
    margin-left: auto;
    gap: 6px;
    flex: 0 0 auto;
}

.ml-nav-item { position: relative; }

.ml-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    border-radius: var(--ml-r-pill);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ml-body);
    white-space: nowrap;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.ml-nav-link:hover {
    color: var(--ml-ink);
    background: var(--ml-surface);
    text-decoration: none;
}
html[data-theme="dark"] .ml-nav-link:hover { background: var(--ml-surface-2); }

.ml-nav-link.is-active {
    color: var(--ml-accent-text);
    background: var(--ml-accent-bg);
    font-weight: 600;
}

/* Blesta supplies Bootstrap Icons classes and this theme only loads Font
   Awesome, so these render as empty boxes that still take up space. Matched
   on the standalone `bi` token: a substring test on "bi-" was defeated by the
   `fa-fw` the templates append, which left a gap before submenu labels. */
i[class~="bi"] { display: none; }
.ml-nav-link i:not(.ml-chev) { font-size: 0.8125rem; opacity: 0.8; }
.ml-chev {
    font-size: 0.5625rem;
    opacity: 0.55;
    margin-left: 0.1rem;
    transition: transform 0.15s ease-out;
}
.ml-has-menu.is-open > .ml-nav-link .ml-chev { transform: rotate(180deg); }
.ml-menu-item { transition: background-color 0.12s ease, color 0.12s ease; }

.ml-nav-end .ml-nav-link {
    border-radius: var(--ml-r);
    border: 1px solid transparent;
}
.ml-nav-end .ml-nav-link:hover { border-color: var(--ml-border); }

.ml-icon-only { padding: 0.4rem 0.55rem; }
.ml-when-dark { display: none; }
html[data-theme="dark"] .ml-when-dark { display: inline-block; }
html[data-theme="dark"] .ml-when-light { display: none; }

.ml-account { padding-left: 0.3rem; }
.ml-avatar {
    width: 26px;
    height: 26px;
    border-radius: var(--ml-r-pill);
    background: var(--ml-accent-bg);
    color: var(--ml-accent-text);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
/* An uploaded picture covers the initials rather than replacing them, so the
   circle is never empty while the image is on its way */
.ml-avatar { position: relative; overflow: hidden; }
.ml-avatar-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
}
/* 11ch cut "Andreas Claesson" mid-surname. Long names still ellipsise, they
   just get the room a two part name actually needs first. */
.ml-account-name { max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Staff signed in as a client: amber, so it never reads as the brand red,
   and its hover deepens the amber instead of falling back to the grey nav hover */
.ml-staff {
    color: #b45309;
    background: rgb(245 158 11 / 0.12);
    border-color: rgb(245 158 11 / 0.45) !important;
}
.ml-staff:hover,
.ml-staff:focus {
    color: #92400e;
    background: rgb(245 158 11 / 0.22);
}
html[data-theme="dark"] .ml-staff { color: #fbbf24; }
html[data-theme="dark"] .ml-staff:hover,
html[data-theme="dark"] .ml-staff:focus { color: #fcd34d; background: rgb(245 158 11 / 0.22); }

/* The only filled action in the header, and it is green like every other
   conversion on the site. */
.ml-cta {
    background: var(--ml-go);
    color: #fff;
    font-weight: 600;
    padding: 0.45rem 1rem;
    box-shadow: var(--ml-shadow-sm);
}
.ml-cta:hover {
    background: var(--ml-go-hover);
    color: #fff;
    text-decoration: none;
    border-color: transparent !important;
}

.ml-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    min-width: 220px;
    padding: 6px;
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    box-shadow: var(--ml-shadow-lg);
    z-index: 120;
    /* Animated rather than display:none so it can fade and slide. Timings and
       the 4px rise match the marketing site's header menus. */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(-4px);
    transition: opacity 0.1s ease-in, transform 0.1s ease-in, visibility 0s linear 0.1s;
}
/* Bridges the 8px gap so the pointer can travel from the link to the menu
   without passing over dead space and closing it. */
.ml-menu::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: -9px;
    height: 9px;
}
.ml-menu-right { left: auto; right: 0; }

.ml-has-menu.is-open > .ml-menu {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
    transition: opacity 0.15s ease-out, transform 0.15s ease-out, visibility 0s;
}
/* Hover opening only where there is a real pointer. Touch keeps the tap
   toggle, and :focus-within gives the same behaviour to the keyboard. */
@media (hover: hover) and (pointer: fine) {
    .ml-has-menu:hover > .ml-menu,
    .ml-has-menu:focus-within > .ml-menu {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: translateY(0);
        transition: opacity 0.15s ease-out, transform 0.15s ease-out, visibility 0s;
    }
    .ml-has-menu:hover > .ml-nav-link .ml-chev,
    .ml-has-menu:focus-within > .ml-nav-link .ml-chev { transform: rotate(180deg); }
}

.ml-menu-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.5rem 0.65rem;
    border: 0;
    background: none;
    border-radius: var(--ml-r);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ml-body);
    text-align: left;
    white-space: nowrap;
}
.ml-menu-item:hover {
    background: var(--ml-surface-2);
    color: var(--ml-ink);
    text-decoration: none;
}
.ml-menu-item i { color: var(--ml-faint); font-size: 0.8125rem; }
.ml-menu-item.is-active {
    color: var(--ml-accent-text);
    background: var(--ml-accent-bg);
}
.ml-menu-item.is-active i { color: var(--ml-accent-text); }
.ml-menu-danger:hover { color: var(--ml-bad-text); background: var(--ml-bad-bg); }
.ml-menu-danger:hover i { color: var(--ml-bad-text); }
.ml-menu-sep {
    height: 1px;
    background: var(--ml-border);
    margin: 5px 0.65rem;
}

.ml-burger {
    display: none;
    width: 38px;
    height: 38px;
    margin-left: auto;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
    background: none;
    padding: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
}
.ml-burger span {
    display: block;
    width: 16px;
    height: 1.5px;
    background: var(--ml-body);
    transition: transform 0.2s ease, opacity 0.2s ease;
}
.ml-burger.is-open span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.ml-burger.is-open span:nth-child(2) { opacity: 0; }
.ml-burger.is-open span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* ------------------------------------------------------------ page head --
   Carries the site's two signature effects: the 32px grid and the red radial
   glow. Used once per page, at the top, and nowhere else. */
.ml-pagehead {
    position: relative;
    overflow: hidden;
    background: var(--ml-canvas);
    border-bottom: 1px solid var(--ml-border);
    padding: 1.875rem 0;
}
.ml-pagehead::before,
.ml-pagehead::after {
    content: "";
    position: absolute;
    pointer-events: none;
}
.ml-pagehead::before {
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='none'%3E%3Cpath d='M0 .5H31.5V32' stroke='%2340404a'/%3E%3C/svg%3E");
    opacity: var(--ml-grid-opacity);
}
html[data-theme="dark"] .ml-pagehead::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='none'%3E%3Cpath d='M0 .5H31.5V32' stroke='%23a1a1ad'/%3E%3C/svg%3E");
}
.ml-pagehead::after {
    top: -280px;
    left: 50%;
    transform: translateX(-50%);
    width: 1100px;
    height: 420px;
    background: radial-gradient(closest-side, var(--ml-glow), transparent);
}
.ml-pagehead .ml-shell {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.ml-pagehead h1 {
    margin: 0;
    font-family: var(--ml-display);
    font-weight: 700;
    font-size: 1.75rem;
    letter-spacing: -0.03em;
    line-height: 1.15;
    color: var(--ml-ink);
}

/* ---------------------------------------------------------------- cards --
   Border-first and flat at rest. Nothing floats unless it is genuinely
   above the page, which here means only menus and modals. */
.card,
.card-blesta,
.panel,
.panel-blesta {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-xl);
    box-shadow: none;
    margin-bottom: 1.5rem;
}
/* Blesta lumps .card-blesta and .panel-blesta into two !important utility
   groups: `.border` (1px solid #dee2e6) and `.rounded-lg` (0.3rem). Both have
   to be matched, or every widget card keeps a 4.5px corner instead of the
   theme's 16px. */
.card-blesta,
.panel-blesta {
    border: 1px solid var(--ml-border) !important;
    border-radius: var(--ml-r-xl) !important;
}

.card-header,
.panel .panel-heading,
.card-blesta > .card-header {
    background: transparent;
    border-bottom: 1px solid var(--ml-hairline);
    padding: 1rem 1.25rem;
    font-family: var(--ml-display);
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--ml-ink);
    border-radius: var(--ml-r-xl) var(--ml-r-xl) 0 0;
}

.card-body,
.panel .panel-body,
.panel-pad {
    padding: 1.25rem;
    color: var(--ml-body);
}

.card-footer,
.panel .panel-footer {
    background: var(--ml-surface-3);
    border-top: 1px solid var(--ml-hairline);
    padding: 0.875rem 1.25rem;
    border-radius: 0 0 var(--ml-r-xl) var(--ml-r-xl);
}
html[data-theme="dark"] .card-footer,
html[data-theme="dark"] .panel .panel-footer {
    background: rgb(255 255 255 / 0.02);
}

.card p { color: var(--ml-body); }

/* Widget nav strip: the filter/section links Blesta puts in a card header. */
.card-nav {
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--ml-hairline);
}
.card-links,
.panel-links,
.nav-tabs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    list-style: none;
    margin: 0;
    /* -0.75rem cancels the first pill's own padding so its text, not its
       background, starts on the card's 1.25rem text column. */
    padding: 0.5rem 0 0.5rem 0;
    margin-left: -0.75rem;
    border: 0;
    font-size: inherit;
}
/* Blesta separates these with a light grey "|" pseudo-element. The pill
   shapes already separate them, and the glyph never sat on the text baseline. */
.card-links > li + li::before,
.panel-links > li + li::before {
    content: "";
    padding: 0;
}
.card-links > li,
.nav-tabs > li {
    margin: 0;
}
.card-links > li > a,
.nav-tabs > li > a,
.nav-tabs .nav-link {
    display: inline-block;
    padding: 0.375rem 0.75rem;
    border: 0;
    border-radius: var(--ml-r-pill);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ml-muted);
    background: none;
    margin: 0;
}
.card-links > li > a:hover,
.nav-tabs > li > a:hover,
.nav-tabs .nav-link:hover {
    background: var(--ml-surface-2);
    color: var(--ml-ink);
    text-decoration: none;
    border: 0;
}
.card-links > li.current > a,
.card-links > li.active > a,
.nav-tabs > li.active > a,
.nav-tabs .nav-link.active {
    background: var(--ml-accent-bg);
    color: var(--ml-accent-text);
    font-weight: 600;
    border: 0;
}
.card-links .badge,
.panel-links .badge,
.nav-tabs .badge {
    margin-left: 0.35rem;
    min-width: 0;
    padding: 0.05rem 0.4rem;
    font-size: 0.625rem;
    font-weight: 600;
    border: 0;
    border-radius: var(--ml-r-pill);
    background: var(--ml-surface-2);
    color: var(--ml-muted);
}
.card-links > li.current > a .badge,
.card-links > li.active > a .badge,
.panel-links > li.current > a .badge,
.nav-tabs > li.active > a .badge,
.nav-tabs .nav-link.active .badge {
    background: var(--ml-accent-line);
    color: var(--ml-accent-text);
}

/* Dashboard tiles. Blesta gives these their own .cards .card rules, which
   outrank a bare .card, so the overrides are scoped the same way. */
.cards { margin: 0 -10px; }
.cards .card {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-xl);
    font-family: var(--ml-sans);
    min-height: 0;
}
.cards .card { padding: 0 !important; }
.cards .card .card-content { width: 100%; padding: 1.25rem; }
.cards .card .card-content .card-value {
    font-family: var(--ml-display);
    font-size: 1.875rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.03em;
    margin-bottom: 0.2rem;
}
.cards .card .card-content .card-label {
    font-size: 0.8125rem;
    font-weight: 400;
    line-height: 1.4;
}
/* client_main_card.pdt no longer emits Blesta's inline colours, so the tiles
   are ours to paint and follow the theme in both modes. */
.cards .card { color: var(--ml-ink); }
.cards .card .card-content .card-value { color: var(--ml-ink); }
.cards .card .card-content .card-label { color: var(--ml-muted); }
.cards a,
.cards a:hover,
.cards a:focus { text-decoration: none; }
.cards a:hover .card { border-color: var(--ml-border-strong); }

/* .card-content is a bare wrapper: .card-nav and .card-body do the padding.
   Giving it padding too pushed every text column 1.25rem right of the rules. */
.card > .card-content {
    padding: 0;
}
.card-value {
    font-family: var(--ml-display);
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--ml-ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.card-label {
    font-size: 0.8125rem;
    color: var(--ml-muted);
    margin-top: 0.25rem;
}
a > .card {
    transition: border-color 0.2s ease;
}
a:hover > .card {
    border-color: var(--ml-accent-line);
    text-decoration: none;
}

/* ------------------------------------------------------------ list group --
   Doubles as the secondary sidebar and the service tab rail. */
.list-group {
    border-radius: var(--ml-r-xl);
    margin-bottom: 1.5rem;
    gap: 0;
}
.list-group .list-group-item,
.list-group-item {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-bottom-width: 0;
    color: var(--ml-body);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.7rem 1rem;
    text-decoration: none !important;
    transition: background-color 0.15s ease, color 0.15s ease;
}
.list-group .list-group-item:first-child {
    border-radius: var(--ml-r-xl) var(--ml-r-xl) 0 0;
}
.list-group .list-group-item:last-child {
    border-bottom-width: 1px;
    border-radius: 0 0 var(--ml-r-xl) var(--ml-r-xl);
}
.list-group .list-group-item:only-child {
    border-radius: var(--ml-r-xl);
}
.list-group-item-action:hover,
a.list-group-item:hover,
a.list-group-item:focus {
    background: var(--ml-surface-2);
    color: var(--ml-ink);
}
.list-group .list-group-item.active,
.list-group-item.active {
    background: var(--ml-accent-bg);
    border-color: var(--ml-border);
    color: var(--ml-accent-text);
    font-weight: 600;
    z-index: auto;
}
.list-group .list-group-item i,
.list-group-item i {
    color: var(--ml-faint);
    margin-right: 0.35rem;
}
.list-group .list-group-item.active i { color: var(--ml-accent-text); }

/* list-options rows (the "change this" prompts in the sidebar). Blesta forces
   their text grey with !important and flips the background to #f8f9fa on hover
   at a specificity a plain .list-group-item-action rule cannot reach. */
.list-group.list-options .list-group-item {
    color: var(--ml-body) !important;
}
.list-group.list-options .list-group-item:hover,
.list-group.list-options a.list-group-item:hover,
.list-group.list-options a.list-group-item:focus {
    background: var(--ml-surface-2);
    color: var(--ml-ink) !important;
}
.list-group.list-options .list-group-item i { color: var(--ml-faint); }

/* Automatic payment row: card mark, the account, and a status dot. */
.ml-autodebit {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
/* Fixed slot so a brand mark and the fallback glyph occupy the same width and
   the labels line up between rows. */
.ml-autodebit-mark {
    flex: 0 0 auto;
    width: 28px;
    display: flex;
    align-items: center;
}
.ml-autodebit-mark img { display: block; height: auto; max-width: none; min-width: 0; margin: 0; }
.ml-autodebit .ml-autodebit-icon { color: var(--ml-faint); margin: 0; flex: 0 0 auto; }
.ml-autodebit-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Four bullets jammed together read as a blob; a little tracking and a step
   back in weight keeps the digits the thing you actually read. */
.ml-mask {
    letter-spacing: 0.1em;
    color: var(--ml-faint);
    font-size: 0.9em;
    vertical-align: 0.05em;
}

.ml-autodebit-dot {
    position: relative;
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ml-faint);
}
.ml-autodebit.is-on .ml-autodebit-dot { background: var(--ml-ok); }
/* Matches the pulsing status dot in the site footer. */
.ml-autodebit.is-on .ml-autodebit-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--ml-ok);
    animation: ml-ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes ml-ping {
    75%, 100% { transform: scale(2.4); opacity: 0; }
}

.card-blesta .list-group,
.card-blesta > .list-group {
    margin: 0;
}
.card-blesta > .list-group .list-group-item {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
}
.card-blesta > .list-group .list-group-item:last-child {
    border-bottom: 0;
}

/* The order plugin spaces these apart with `margin-bottom: 20px`, so each is
   its own card and needs a full border and radius rather than the stacked
   list treatment. */
.package-groups .list-group-item,
.package-groups .list-group-item:first-child,
.package-groups .list-group-item:last-child,
.package-groups .list-group-item:only-child {
    border-width: 1px;
    border-radius: var(--ml-r-xl);
}
.package-groups .list-group-item h4 { margin: 0; }

/* --------------------------------------------------------------- tables --
   Hairline separation, no zebra. Striping is what dated the old panel most. */
table {
    border: 0;
}

.table,
.table-curved {
    width: 100%;
    margin-bottom: 0;
    border-collapse: collapse;
    color: var(--ml-body);
    font-size: 0.8125rem;
}

.table > thead > tr > th,
.table-curved th,
.table > thead > tr > th > a {
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--ml-border);
    padding: 0.6rem 0.5rem;
    font-family: var(--ml-sans);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ml-muted);
    white-space: nowrap;
}
.table > thead > tr > th > a { padding: 0; border: 0; display: inline-block; }
.table > thead > tr > th > a:hover { color: var(--ml-ink); text-decoration: none; }

.table > tbody > tr > td,
.table-curved tbody > tr > td,
.table-curved tbody > tr > td:first-child {
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--ml-hairline);
    border-radius: 0;
    padding: 0.65rem 0.5rem;
    vertical-align: middle;
    color: var(--ml-body);
}
.table > tbody > tr:last-child > td { border-bottom: 0; }
.table > thead > tr > th:first-child,
.table > tbody > tr > td:first-child { padding-left: 1.25rem; }
.table > thead > tr > th:last-child,
.table > tbody > tr > td:last-child { padding-right: 1.25rem; }

/* That gutter exists for tables that run full bleed to the card's edge. A
   module service tab is not one: it renders inside an already padded body, so
   the gutter lands on top of the padding and pushes the first column past the
   tab's own heading. Flush to the text above it instead. */
#client_services_manage .table > thead > tr > th:first-child,
#client_services_manage .table > tbody > tr > td:first-child { padding-left: 0; }
#client_services_manage .table > thead > tr > th:last-child,
#client_services_manage .table > tbody > tr > td:last-child { padding-right: 0; }

/* Unless the tab wrapped its table in .table-responsive, which draws its own
   framed box. Inside that frame the gutter is what keeps the text off the
   border, so it has to come back. */
#client_services_manage .table-responsive .table > thead > tr > th:first-child,
#client_services_manage .table-responsive .table > tbody > tr > td:first-child { padding-left: 1.25rem; }
#client_services_manage .table-responsive .table > thead > tr > th:last-child,
#client_services_manage .table-responsive .table > tbody > tr > td:last-child { padding-right: 1.25rem; }

/* Kill striping. Blesta paints the cells, not the row, so these mirror its
   selectors exactly and win on source order. */
.table-striped > tbody > tr:nth-child(2n+1) > td,
.table-striped-alt > tbody > tr:nth-child(2n+1) > td,
.table-striped > tbody > tr:nth-child(2n+1) > th,
.table-striped-alt > tbody > tr:nth-child(2n+1) > th,
.table-striped > tbody > tr:nth-child(2n) > td,
.table-striped-alt > tbody > tr:nth-child(2n) > td,
.table-striped > tbody > tr:nth-child(2n) > th,
.table-striped-alt > tbody > tr:nth-child(2n) > th,
.table-striped-alt > tbody > tr:nth-child(4n+3) > td,
.table-striped-alt > tbody > tr:nth-child(4n+3) > th,
.table-striped tbody tr:nth-of-type(odd),
.table-striped tbody tr:nth-of-type(even),
.table-striped-alt tbody tr:nth-of-type(odd),
.table-striped-alt tbody tr:nth-of-type(even) {
    background-color: transparent;
}
/* Blesta's cell hover is !important, so this has to be too. */
.table-hover > tbody > tr:hover > td,
.table-hover > tbody > tr:hover > th {
    background-color: var(--ml-row-hover) !important;
}

.table > tbody > tr > td strong { color: var(--ml-ink); }

.table-curved td,
.table-curved tbody > tr > td,
.table-curved tbody > tr > td:first-child,
.table-curved th,
.table-curved th:first-child,
.table-curved th:last-child {
    border-left: 0;
    border-right: 0;
    border-top: 0;
}
.table-curved,
.table-curved th,
.table-curved th:first-child,
.table-curved th:last-child,
.table-curved th:only-child,
.table-curved tr:last-child td:first-child,
.table-curved tr:last-child td:last-child,
.table-curved thead tr:first-child td:first-child,
.table-curved thead tr:first-child td:last-child {
    border-radius: 0;
    border-collapse: collapse;
}

.table-responsive {
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    overflow-x: auto;
    margin-bottom: 1rem;
}
@media (min-width: 768px) {
    .table-responsive {
        overflow: visible;
    }
}
.table-responsive:has(.dropdown-menu.show) {
    overflow: visible;
}
.table-responsive .table th { border-top: 0; }
.card-body > .table-responsive:last-child,
.card-content > .table-responsive:only-child {
    margin-bottom: 0;
}
/* A table that fills a card body runs edge to edge and drops its own frame. */
.card > .card-content > .table-responsive,
.card-body > .table-responsive {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    margin-left: -1.25rem;
    margin-right: -1.25rem;
    width: auto;
}

/* Expandable service rows. */
tr.expand { cursor: pointer; }
tr.expand td:last-of-type::after {
    content: "";
    width: 0.75rem;
    height: 0.75rem;
    background-color: currentColor;
    -webkit-mask: var(--ml-i-chevron-down) no-repeat center / contain;
    mask: var(--ml-i-chevron-down) no-repeat center / contain;
    display: inline-block;
    /* The negative right margin lets the glyph sit inside the cell's existing
       padding, so it costs no extra table width and cannot force a scrollbar. */
    margin-left: 0.6rem;
    margin-right: -0.6rem;
    vertical-align: middle;
    font-size: 0.625rem;
    color: var(--ml-faint);
}
tr.expand.expanded td:last-of-type::after { -webkit-mask-image: var(--ml-i-chevron-up); mask-image: var(--ml-i-chevron-up); }
/* jQuery 3.7 .show()/.toggle() writes an inline `display: block` onto whatever
   it reveals. On a <tr> that drops the row out of the table layout: each row
   becomes its own shrink-to-fit box, so a colspan cell stops spanning and the
   columns of one row no longer line up with the next. Blesta hits this in two
   places, the expanded service row and the domain pricing table's Show All, so
   the rule covers every row rather than those two selectors. Only the shown
   state carries "block" - .hide() writes "none". */
tr[style*="block"] { display: table-row !important; }
/* Blesta gives this cell `border-top: 2px solid #ccc` at a specificity a plain
   `tr.expand_details > td` rule cannot reach, which drew a light bar above the
   panel. Its selectors are mirrored here, and the row-hover highlight is
   suppressed: an open detail panel is not a row you are picking out of a list.
   The hover rule it has to beat is !important, hence the flag. */
.table > tbody > tr.expand_details > td,
.table > tbody > tr.expand_details > td:hover,
.table-hover > tbody > tr.expand_details:hover > td {
    background-color: var(--ml-expand-bg) !important;
    border-top: 1px solid var(--ml-border);
    padding: 0;
}

th > a.asc::after,
th > a.desc::after {
    content: "";
    display: inline-block;
    width: 0.75rem;
    height: 0.75rem;
    vertical-align: -0.1em;
    margin-left: 0.35rem;
    background-color: var(--ml-accent);
    -webkit-mask: var(--ml-i-arrow-up) no-repeat center / contain;
    mask: var(--ml-i-arrow-up) no-repeat center / contain;
}
th > a.desc::after { -webkit-mask-image: var(--ml-i-arrow-down); mask-image: var(--ml-i-arrow-down); }

/* Money and identifiers line up when they are tabular. */
.currency_value,
.label-currency,
.total-summary .table tbody > tr > td,
.totals tbody > tr > td,
.cart-summary .table > tbody > tr > td {
    font-variant-numeric: tabular-nums;
}
.total-summary h4 { color: var(--ml-ink); }

/* -------------------------------------------------------------- buttons --
   Green spends money or creates something. Red is identity and destruction.
   Grey is everything else. The three never swap roles. */
.btn {
    font-family: var(--ml-sans);
    font-size: 0.8125rem;
    font-weight: 600;
    border-radius: var(--ml-r);
    border: 1px solid transparent;
    padding: 0.5rem 1rem;
    line-height: 1.4;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
    box-shadow: none;
}
.btn:focus, .btn.focus { box-shadow: none; }

.btn-sm, .btn-xs {
    font-size: 0.75rem;
    padding: 0.3rem 0.6rem;
    border-radius: var(--ml-r-sm);
}
.btn-med { padding: 0.6rem 1rem; }
.btn-lg { font-size: 0.9375rem; padding: 0.7rem 1.5rem; }

/* Neutral / outline: the default for navigation-ish actions. */
.btn-light,
.btn-secondary,
.btn-default,
.btn-outline-secondary {
    background: var(--ml-surface);
    border-color: var(--ml-border-strong);
    color: var(--ml-body);
}
.btn-light:focus, .btn-light.focus,
.btn-secondary:focus, .btn-secondary.focus,
.btn-default:focus, .btn-default.focus,
.btn-outline-secondary:focus, .btn-outline-secondary.focus,
.btn-outline-light:focus, .btn-outline-light.focus {
    background-color: var(--ml-surface);
    border-color: var(--ml-border-strong);
    color: var(--ml-body);
}
.btn-success:focus, .btn-success.focus,
.btn-primary:focus, .btn-primary.focus {
    background-color: var(--ml-go);
    border-color: var(--ml-go);
    color: #fff;
}
.btn-danger:focus, .btn-danger.focus {
    background-color: var(--ml-accent-solid);
    border-color: var(--ml-accent-solid);
    color: #fff;
}
.btn-info:focus, .btn-info.focus { background-color: var(--ml-info); border-color: var(--ml-info); color: #fff; }
.btn-warning:focus, .btn-warning.focus { background-color: var(--ml-warn); border-color: var(--ml-warn); color: #0a0a0c; }

.btn-light:hover,
.btn-secondary:hover,
.btn-default:hover,
.btn-outline-secondary:hover {
    background: var(--ml-surface-2);
    border-color: var(--ml-border-strong);
    color: var(--ml-ink);
}
.btn-light:active,
.btn-secondary:active,
.btn-default:active,
.btn-outline-secondary:active,
.btn-light:not(:disabled):not(.disabled):active,
.btn-secondary:not(:disabled):not(.disabled):active,
.btn-default:not(:disabled):not(.disabled):active,
.btn-outline-secondary:not(:disabled):not(.disabled):active {
    background-color: var(--ml-surface-3);
    border-color: var(--ml-border-strong);
    color: var(--ml-ink);
}

/* Conversion. Blesta uses btn-success for pay, order, renew and add. */
.btn-success,
.btn-primary {
    background: var(--ml-go);
    border-color: var(--ml-go);
    color: #fff;
    box-shadow: var(--ml-shadow-sm);
}
.btn-success:hover,
.btn-primary:hover {
    background: var(--ml-go-hover);
    border-color: var(--ml-go-hover);
    color: #fff;
}
.btn-success:active,
.btn-primary:active,
.btn-success:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled):active {
    background: var(--ml-go-active);
    border-color: var(--ml-go-active);
}

.btn-danger {
    background: var(--ml-accent-solid);
    border-color: var(--ml-accent-solid);
    color: #fff;
    box-shadow: var(--ml-shadow-sm);
}
.btn-danger:hover {
    background: var(--ml-accent-solid-hover);
    border-color: var(--ml-accent-solid-hover);
    color: #fff;
}

.btn-info {
    background: var(--ml-info);
    border-color: var(--ml-info);
    color: #fff;
}
.btn-warning {
    background: var(--ml-warn);
    border-color: var(--ml-warn);
    color: #0a0a0c;
}
.btn-link { color: var(--ml-accent); box-shadow: none; }

.btn-block { display: block; width: 100%; }
.btn-group > .btn { border-radius: var(--ml-r); }
.btn-group > .btn:not(:last-child) { margin-right: 4px; }
.btn i { margin-right: 0.3rem; }
.btn i:only-child { margin-right: 0; }

/* --------------------------------------------------------------- forms -- */
.form-control,
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="url"],
input[type="search"],
select,
textarea {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border-strong);
    border-radius: var(--ml-r);
    color: var(--ml-ink);
    font-family: var(--ml-sans);
    font-size: 0.875rem;
    padding: 0.5rem 0.75rem;
    height: auto;
    box-shadow: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.form-control:focus,
input:focus,
select:focus,
textarea:focus {
    background: var(--ml-surface);
    border-color: var(--ml-accent-ring);
    color: var(--ml-ink);
    box-shadow: 0 0 0 3px rgb(244 76 92 / 0.15);
    outline: none;
}
.form-control::placeholder { color: var(--ml-faint); }
.form-control:disabled,
.form-control[readonly] {
    background: var(--ml-surface-2);
    color: var(--ml-muted);
}
select.form-control:not([multiple]) {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%236f6f7a' stroke-width='1.6'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.7rem center;
    padding-right: 2rem;
}
.form-group { margin-bottom: 1rem; }

.checkbox,
.radio,
.form-check {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    padding-left: 0;
}
.checkbox label,
.radio label,
.form-check-label {
    color: var(--ml-body);
    font-size: 0.875rem;
    font-weight: 400;
    margin: 0;
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}
.form-check-input {
    position: static;
    margin: 0.2rem 0 0 0;
}
.checkbox-inline,
.checkbox-inline label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 400;
    color: var(--ml-body);
    font-size: 0.875rem;
}
.checkbox-inline {
    margin-right: 1rem;
    margin-bottom: 0.35rem;
}
.checkbox-inline label {
    margin: 0;
}
.checkbox-inline input[type="checkbox"] {
    margin-top: 0;
}
#two_factor_qr {
    background: #ffffff;
    padding: 0.5rem;
    border-radius: var(--ml-r-sm);
    display: inline-block;
}
/* The platform draws these, and on a dark surface it picks a pale ring that
   belongs to no palette here. Drawn by hand instead: a plain box or circle
   that fills in when checked. The margin-top keeps the control level with the
   first line of a label that wraps, since those rows are top aligned. */
input[type="checkbox"],
input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    width: 15px;
    height: 15px;
    margin-top: 0.2rem;
    flex: 0 0 auto;
    border: 1px solid var(--ml-border-strong);
    background: transparent;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
input[type="checkbox"] { border-radius: 3px; }
input[type="radio"] { border-radius: 50%; }

input[type="checkbox"]:checked,
input[type="radio"]:checked {
    border-color: var(--ml-go);
}
/* Painted marks, not a filled control masked with the surface colour: that
   would show as a mismatched block wherever the row sits on anything else. */
input[type="checkbox"]:checked {
    background:
        var(--ml-go)
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2 6.2 4.6 8.8 10 3.4'/%3E%3C/svg%3E")
        center / 11px 11px no-repeat;
}
input[type="radio"]:checked {
    background: radial-gradient(circle at center, var(--ml-go) 0 3.5px, transparent 3.6px);
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
    opacity: 0.5;
}
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 2px solid var(--ml-accent-ring);
    outline-offset: 2px;
}

/* ------------------------------------------------- package options ------
   Quantity options arrive as: label.d-block, tooltip link, slider, number
   input, label.d-block. Both d-block labels are `display:block !important`,
   which drops the tooltip onto the slider and the unit price under the box. */
.form-group > label.d-block:first-child {
    display: inline-block !important;
    margin-right: 0.15rem;
    vertical-align: middle;
}
.form-group > label.d-block:first-child + a[data-toggle="tooltip"] {
    display: inline-block;
    /* The label beside it is vertical-align: middle here rather than baseline,
       which moves the reference the icon aligns against, so this layout needs
       its own value. Measured: middle leaves the icon 3.5px low, this 0.5px. */
    vertical-align: 0.1em;
}
.form-group > .slider.slider-horizontal {
    display: block;
    width: 100%;
    margin: 0.85rem 0 1rem;
}
.form-group > input[type="number"].form-control {
    display: inline-block;
    width: 6.5rem;
    vertical-align: middle;
}
.form-group > input[type="number"].form-control + label.d-block {
    display: inline-block !important;
    margin: 0 0 0 0.6rem;
    vertical-align: middle;
    color: var(--ml-muted);
}

/* bootstrap-slider still ships Bootstrap 3 gradients, so the track rendered as
   a white bar and the handle as a stock blue circle. */
.slider-track {
    background: var(--ml-surface-2) !important;
    background-image: none !important;
    box-shadow: none !important;
}
.slider-selection {
    background: var(--ml-accent-ring) !important;
    background-image: none !important;
    box-shadow: none !important;
}
.slider-track-low,
.slider-track-high { background: transparent !important; }
.slider-handle {
    background: var(--ml-accent-ring) !important;
    background-image: none !important;
    border: 2px solid var(--ml-surface);
    box-shadow: var(--ml-shadow-sm) !important;
    opacity: 1;
}
.slider .tooltip-inner {
    background: var(--ml-ink) !important;
    color: var(--ml-canvas) !important;
    border-radius: var(--ml-r-sm);
    font-family: var(--ml-sans);
}
.slider .tooltip.top .tooltip-arrow { border-top-color: var(--ml-ink) !important; }

/* Order summary card. plugins/order/.../order.css loads after this file and
   sets `.card-order .table > tbody > tr > td { padding: 8px 4px 4px 4px }` at
   the same specificity, which left the header indented past its own rows.
   The extra .card qualifier wins without needing !important. */
.card-order.card .table > thead > tr > th,
.card-order.card .table > tbody > tr > td {
    padding: 0.5rem 0.4rem;
    border: 0;
}
.card-order.card .table > thead > tr > th:first-child,
.card-order.card .table > tbody > tr > td:first-child { padding-left: 0; }
.card-order.card .table > thead > tr > th:last-child,
.card-order.card .table > tbody > tr > td:last-child { padding-right: 0; }
.card-order.card .table > thead > tr > th {
    border-bottom: 1px solid var(--ml-border);
}
/* Floating a table cell forces display:block and drops it out of the row,
   which is what made the price column drift from its header. */
.card-order.card .table td.price-col.float-right {
    float: none !important;
    display: table-cell;
    text-align: right;
}
.card-order.card .table > thead > tr > th:last-child { text-align: right; }

/* Order form list. The title and its button sit in sibling columns with no
   vertical alignment, so the heading's own bottom margin lifted it above the
   button's centre. */
.order-listing .card > .row { align-items: center; }
.order-listing .head-item h3 { margin-bottom: 0; }

/* The order-form spec list, rendered on the forms listing by the spec helper.
   These rules live in the order template's own css, which this page does not
   load, so they are repeated here for the listing to pick them up. */
.order-listing .ml-specs { list-style: none; padding: 0; margin: 0.75rem 0 0; }
.order-listing .ml-specs li {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.25rem 0;
    line-height: 1.4;
}
.order-listing .ml-specs .fas {
    color: var(--ml-muted, #6c757d);
    font-size: 0.8125rem;
    flex: 0 0 auto;
}
.order-listing .ml-specs-lead { margin-bottom: 0.5rem; }
.order-listing .ml-group-icon-inline { color: var(--ml-ok-text, #048c3c); margin-right: 0.4rem; }

/* Order form pricing table. plugins/order/.../order.css loads after this file
   and hardcodes #fff backgrounds, #efefef bands and dashed #efefef rules, so
   each override carries one extra class to win on specificity rather than
   order. The .card-blesta border is !important, hence the flag on selected. */
.package.card {
    background: var(--ml-surface);
    box-shadow: none;
}
.package.card .package-name {
    border-radius: var(--ml-r-xl) var(--ml-r-xl) 0 0;
    border-bottom: 1px solid var(--ml-hairline);
}
.package.card .price-box {
    background-color: var(--ml-surface-2);
    border-bottom: 1px solid var(--ml-hairline);
}
.package.card .price-box p {
    color: var(--ml-muted);
    border-bottom: 0;
}
.package.card p {
    border-bottom: 1px solid var(--ml-hairline);
    color: var(--ml-body);
}
.package.card .instructions {
    color: var(--ml-muted);
    font-style: normal;
}
.package.card .order {
    background-color: transparent;
    border-top: 1px solid var(--ml-hairline);
    border-radius: 0 0 var(--ml-r-xl) var(--ml-r-xl);
}
/* Green marks the plan you are buying, matching its Selected button. */
.package.card.selected {
    border-color: var(--ml-go) !important;
    box-shadow: inset 0 0 0 1px var(--ml-go);
}

/* Domain search. The order plugin paints a light globe illustration as a
   background image positioned half off the card, which glares on a dark canvas
   and carries no information. The inner .well is already the panel, so this
   just gets out of its way. Extra class to beat order.css, which loads later. */
.card .whois,
.whois.col-md-12 {
    background: transparent;
    background-image: none;
    padding: 0;
}
/* .checkbox-inline is a Bootstrap 3 class with no styles in Bootstrap 4, so the
   TLD toggles had no spacing at all. */
.whois .tlds .checkbox-inline {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0 0.75rem 0.35rem 0;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ml-body);
}
.whois .tlds .checkbox-inline input { margin: 0; }
.whois .show_more { margin-left: 0.5rem; }

/* -------------------------------------------------------------- alerts -- */
.alert {
    border: 1px solid;
    border-radius: var(--ml-r-lg);
    padding: 0.875rem 1rem;
    font-size: 0.875rem;
    margin-bottom: 1.25rem;
}
/* Every inline alert-info in the client templates is a "no results" empty
   state, not a notice. Colour that asks for attention is wrong for a
   non-event, so these stay quiet. Runtime notices from message.pdt carry
   .alert-dismissable and keep an informational tint. */
.alert-info {
    background: var(--ml-surface-3);
    border-color: var(--ml-border);
    color: var(--ml-muted);
}
html[data-theme="dark"] .alert-info { background: rgb(255 255 255 / 0.03); }
.alert-info.alert-dismissable {
    background: var(--ml-info-bg);
    border-color: var(--ml-info-line);
    color: var(--ml-info-text);
}
.alert-success { background: var(--ml-ok-bg);   border-color: var(--ml-ok-line);   color: var(--ml-ok-text); }
.alert-warning { background: var(--ml-warn-bg); border-color: var(--ml-warn-line); color: var(--ml-warn-text); }
.alert-danger  { background: var(--ml-bad-bg);  border-color: var(--ml-bad-line);  color: var(--ml-bad-text); }
/* An expanded service or domain row is already a panel with its own surface.
   The plugin puts its empty state in an .alert, which then reads as a second
   card floating inside the first one - inset by the alert's margin and rounded
   against the row's square edges. Inside a detail row the alert is just text. */
tr.expand_details .alert {
    background: transparent;
    border: 0;
    border-radius: 0;
    /* the plugin hangs a .mb-2 utility on it, and that one is !important */
    margin: 0 !important;
    /* Blesta gives the detail cell no padding of its own and lets the content
       provide it, so the alert keeps its padding - matched to a first-column
       cell so the text lines up with the column above it. */
    padding: 0.65rem 1.25rem;
}
tr.expand_details .alert > p:last-child { margin-bottom: 0; }

/* Inline links only. message.pdt renders its action as <a class="btn btn-info">
   inside the alert, and colour:inherit there paints the button's label in the
   alert's text colour on the button's own background - unreadable. */
.alert a:not(.btn) { color: inherit; font-weight: 600; text-decoration: underline; }
/* Blesta writes .alert-dismissable, not Bootstrap's .alert-dismissible, so
   Bootstrap never positions the close button and it floats on the first text
   line. Pinned to the corner instead, with room reserved so a right aligned
   action button cannot run under it. */
.alert-dismissable { padding-right: 2.25rem; }
.alert { position: relative; }
/* Blesta's application.css sets .alert .btn { margin-top: 10px }, from when the
   action always sat on its own line below the text. Beside the text it just
   drops the button off centre. Only zeroed inside the side by side row, so an
   alert that still stacks keeps its gap. */
.alert .d-sm-flex .btn { margin-top: 0; }
.alert .close {
    position: absolute;
    top: 0.4rem;
    right: 0.6rem;
    color: inherit;
    opacity: 0.5;
    text-shadow: none;
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1;
    padding: 0.2rem 0.35rem;
}
.alert .close:hover { opacity: 1; }
.panel .card .panel-body .alert { margin-bottom: 0; }

/* -------------------------------------------------------------- badges --
   Status vocabulary matches the marketing site's status badge exactly. */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid transparent;
    border-radius: var(--ml-r-pill);
    font-family: var(--ml-sans);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.5;
    vertical-align: middle;
    background: var(--ml-surface-2);
    color: var(--ml-muted);
}
.badge-success { background: var(--ml-ok-bg);   border-color: var(--ml-ok-line);   color: var(--ml-ok-text); }
.badge-danger  { background: var(--ml-bad-bg);  border-color: var(--ml-bad-line);  color: var(--ml-bad-text); }
.badge-warning { background: var(--ml-warn-bg); border-color: var(--ml-warn-line); color: var(--ml-warn-text); }
.badge-info    { background: var(--ml-info-bg); border-color: var(--ml-info-line); color: var(--ml-info-text); }
.badge-pill { border-radius: var(--ml-r-pill); }

/* A dot in front of a status badge, the way the site marks system health. */
.badge-success::before,
.badge-danger::before,
.badge-warning::before,
.badge-info::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}

/* -------------------------------------------------------- service panel -- */
.service-info label,
.panel-pad label {
    display: block;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ml-faint);
    margin: 0 0 0.15rem;
}
.panel .panel-body .service-info h4,
.service-info h4,
.panel-pad h4 {
    font-family: var(--ml-sans);
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ml-ink);
    margin: 0 0 1rem;
}
.panel .panel-body h4,
.card-body .service-info h4 {
    border-bottom: 0;
    padding-bottom: 0;
}
.col-border { border-right: 1px solid var(--ml-hairline); }
@media (max-width: 767px) { .col-border { border-right: 0; } }

/* .bg-light is a utility, not a component: Blesta puts it on list rows as well
   as panels. Colour only, so it cannot round each row into its own box or
   fight the list's own padding. */
.bg-light {
    background-color: var(--ml-surface-3) !important;
    color: var(--ml-body) !important;
    border-color: var(--ml-border) !important;
}
/* These are real components that sit on a card, so they own their shape and
   need to separate from the surface behind them. */
.top-focus-box,
.tab-pane .top-focus-box,
.well,
form.widget_filter_form {
    background-color: var(--ml-surface-3) !important;
    color: var(--ml-body) !important;
    border-color: var(--ml-border) !important;
    border-radius: var(--ml-r-lg);
    padding: 1rem;
}
html[data-theme="dark"] .top-focus-box,
html[data-theme="dark"] .well,
html[data-theme="dark"] form.widget_filter_form {
    background-color: rgb(255 255 255 / 0.03) !important;
}
a.top-focus-box:hover, a.top-focus-box:focus,
a.bg-light:hover, a.bg-light:focus,
a.well:hover, a.well:focus {
    background-color: var(--ml-surface-2) !important;
    color: var(--ml-ink) !important;
}
.well { border: 1px solid var(--ml-border) !important; }
.top-focus-box .help-block { color: var(--ml-muted); }

address { color: var(--ml-body); font-style: normal; line-height: 1.7; }
address > strong { color: var(--ml-ink); }

/* --------------------------------------------------------------- modals -- */
.modal-content {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-xl);
    box-shadow: var(--ml-shadow-lg);
}
.modal-header,
.modal-footer {
    border-color: var(--ml-hairline);
    padding: 1rem 1.25rem;
}
.modal-body { padding: 1.25rem; color: var(--ml-body); }
.modal-backdrop.show { opacity: 0.6; }
.close {
    color: var(--ml-muted);
    text-shadow: none;
    opacity: 0.7;
    font-weight: 400;
}
.close:hover { color: var(--ml-ink); opacity: 1; }

/* ---------------------------------------------------- bootstrap dropdown --
   Core templates still emit Bootstrap dropdowns in a few places. */
.dropdown-menu {
    background: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    box-shadow: var(--ml-shadow-lg);
    padding: 6px;
    font-size: 0.8125rem;
}
.dropdown-item,
.dropdown-menu li > a,
ul.dropdown-menu li a {
    display: block;
    border-radius: var(--ml-r);
    padding: 0.5rem 0.65rem;
    color: var(--ml-ink) !important;
    font-weight: 500;
    text-decoration: none;
}
.dropdown-item:hover,
.dropdown-item:focus,
.dropdown-menu li > a:hover,
.dropdown-menu li > a:focus,
ul.dropdown-menu li a:hover,
ul.dropdown-menu li a:focus {
    background-color: var(--ml-surface-2) !important;
    color: var(--ml-ink) !important;
    text-decoration: none;
}
.dropdown-divider { border-color: var(--ml-border); margin: 5px 0.65rem; }

/* ---------------------------------------------------------- pagination -- */
/* Blesta compiled Bootstrap with a compound `div.pagination ul.pagination li a`
   selector and stacks !important colour utilities on top
   (`.pagination .page-item .page-link { color:#6c757d !important }`), so a
   plain .page-link rule never won. Both markup shapes are matched below. */
.pagination { gap: 4px; }
.page-link {
    border-radius: var(--ml-r) !important;
    font-size: 0.8125rem;
    padding: 0.35rem 0.7rem;
}
.pagination .page-item .page-link,
div.pagination ul.pagination li a,
div.pagination ul.pagination li .page-link {
    background-color: var(--ml-surface) !important;
    border-color: var(--ml-border) !important;
    color: var(--ml-body) !important;
}
.pagination .page-item a.page-link:hover,
.pagination .page-item a.page-link:focus,
div.pagination ul.pagination li a:hover,
div.pagination ul.pagination li a:focus {
    background-color: var(--ml-surface-2) !important;
    border-color: var(--ml-border-strong) !important;
    color: var(--ml-ink) !important;
}
.pagination .page-item.active .page-link,
div.pagination ul.pagination li.active a,
div.pagination ul.pagination li.active .page-link {
    background-color: var(--ml-accent-solid) !important;
    border-color: var(--ml-accent-solid) !important;
    color: #fff !important;
}
.pagination .page-item.disabled .page-link,
div.pagination ul.pagination li.disabled a,
div.pagination ul.pagination li.disabled .page-link {
    background-color: var(--ml-surface) !important;
    border-color: var(--ml-border) !important;
    color: var(--ml-faint) !important;
}

.progress { background: var(--ml-surface-2); border-radius: var(--ml-r-pill); height: 8px; }
.progress-bar { background: var(--ml-go); }

/* ---------------------------------------------------------------- login --
   No page head here, so the auth screen carries the glow itself. */
.row.login {
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
}
.row.login > div[class^="col-"],
.row.login > div[class*=" col-"] {
    flex: 0 0 100%;
    max-width: 100%;
    margin-left: 0;
}
.row.login h2 {
    font-family: var(--ml-display);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    text-align: center;
}
.row.login h2 .fa-lock { display: none; }
.row.login h4 { text-align: center; font-size: 1rem; color: var(--ml-muted); font-family: var(--ml-sans); font-weight: 400; }
.row.login p { text-align: center; }
.row.login hr { display: none; }
/* Auth screens suppress the header, so the wordmark stands in for it. */
.ml-auth-brand {
    position: relative;
    z-index: 2;
    text-align: center;
    padding: 3rem 1rem 0;
}
.ml-auth-brand img { height: 30px; width: auto; }

main.ml-shell-auth::before {
    content: "";
    position: fixed;
    top: -180px;
    left: 50%;
    transform: translateX(-50%);
    width: 700px;
    height: 380px;
    background: radial-gradient(closest-side, var(--ml-glow), transparent);
    pointer-events: none;
    z-index: 0;
}
main.ml-shell-auth > .row { position: relative; z-index: 1; }

/* --------------------------------------------------------------- footer -- */
.ml-foot {
    border-top: 1px solid var(--ml-border);
    background: var(--ml-surface-2);
    margin-top: auto;
}
html[data-theme="dark"] .ml-foot { background: rgb(255 255 255 / 0.02); }

.ml-foot-top {
    display: grid;
    grid-template-columns: 1.6fr repeat(3, 1fr);
    gap: 2.5rem;
    padding: 3rem 0 2rem;
}
.ml-foot-brand img { height: 26px; width: auto; margin-bottom: 0.875rem; }
.ml-foot-brand p {
    font-size: 0.8125rem;
    color: var(--ml-muted);
    max-width: 30ch;
    line-height: 1.65;
    margin: 0;
}
.ml-pay {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.15rem;
    list-style: none;
    margin: 1.15rem 0 0;
    padding: 0;
}
.ml-pay li { display: flex; align-items: center; }
/* Resets the 26px logo sizing that .ml-foot-brand img otherwise imposes. */
.ml-pay img {
    display: block;
    height: auto;
    max-width: none;
    min-width: 0;
    margin: 0;
    opacity: 0.75;
}

.ml-foot-col h2 {
    font-family: var(--ml-sans);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ml-faint);
    margin: 0 0 0.875rem;
}
.ml-foot-col ul { list-style: none; margin: 0; padding: 0; }
.ml-foot-col li { margin-bottom: 0.5rem; }
.ml-foot-col a {
    font-size: 0.8125rem;
    color: var(--ml-body);
}
.ml-foot-col a:hover { color: var(--ml-accent); }

.ml-foot-legal {
    border-top: 1px solid var(--ml-border);
    padding: 1.25rem 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.5rem;
    justify-content: space-between;
}
.ml-foot-legal p {
    margin: 0;
    font-size: 0.75rem;
    color: var(--ml-faint);
}

/* ------------------------------------------------- dark-safe sweep ------
   An audit of every stylesheet Blesta loads (application.css plus the order
   plugin's order.css) found 95 rules that paint a light background, border or
   text on components this panel actually renders. The ones not already handled
   above are neutralised here, so nothing falls back to Bootstrap grey in dark
   mode. Values come from the tokens, so light mode gains the warm neutrals too. */

/* Buttons. :active is a momentary press, .active is a persistent selection
   such as the currency toggle, so they read differently on purpose. */
.btn-light:not(:disabled):not(.disabled):active,
.btn-secondary:not(:disabled):not(.disabled):active,
.btn-default:not(:disabled):not(.disabled):active,
.btn-outline-secondary:not(:disabled):not(.disabled):active,
.btn-outline-light:not(:disabled):not(.disabled):active,
.btn-default:active,
.show > .btn-light.dropdown-toggle,
.show > .btn-secondary.dropdown-toggle {
    background-color: var(--ml-surface-2);
    border-color: var(--ml-border-strong);
    color: var(--ml-ink);
}
.btn-light:not(:disabled):not(.disabled).active,
.btn-secondary:not(:disabled):not(.disabled).active,
.btn-default:not(:disabled):not(.disabled).active,
.btn-outline-secondary:not(:disabled):not(.disabled).active,
.btn-outline-light:not(:disabled):not(.disabled).active,
.btn-default.active {
    background-color: var(--ml-accent-bg);
    border-color: var(--ml-accent-line);
    color: var(--ml-accent-text);
}
.btn-light.disabled, .btn-light:disabled,
.btn-secondary.disabled, .btn-secondary:disabled,
.btn-default.disabled, .btn-default:disabled {
    background-color: var(--ml-surface-2);
    border-color: var(--ml-border);
    color: var(--ml-faint);
}
.btn-outline-light {
    border-color: var(--ml-border-strong);
    color: var(--ml-body);
}
.btn-outline-light:hover {
    background-color: var(--ml-surface-2);
    border-color: var(--ml-border-strong);
    color: var(--ml-ink);
}
.badge-light { background-color: var(--ml-surface-2); color: var(--ml-muted); }

/* Tab strips. Blesta pins the active tab's text with
   `.nav .nav-item .nav-link.active { color:#343a40 !important }`, which landed
   dark grey on the accent tint and was unreadable. */
.nav .nav-item .nav-link.active,
.nav .nav-tabs li .nav-link.active,
.nav-tabs .nav-item .nav-link.active,
.nav-tabs li.active > a {
    color: var(--ml-accent-text) !important;
}
.nav-tabs .nav-link.active,
.nav-tabs li a.active,
.nav-tabs li.active a,
.nav-tabs .nav-item.show .nav-link {
    background-color: var(--ml-accent-bg);
    border-color: transparent;
}
.nav-tabs .nav-link:hover,
.nav-tabs li a:hover,
.nav-tabs .nav-link:focus,
.nav-tabs li a:focus { border-color: transparent; }
/* Idle tabs: Blesta's `a.text-secondary:hover` group sets #494f54 !important
   at (0,4,1), which is near-black on the hover surface. The active-tab rule
   below is (0,5,1) so it still wins for the selected tab. */
.nav .nav-item a.nav-link:hover,
.nav .nav-item a.nav-link:focus,
.nav .nav-tabs li a:hover,
.nav .nav-tabs li a:focus,
.nav-tabs .nav li a:hover,
.nav-tabs .nav li a:focus {
    color: var(--ml-ink) !important;
}
/* Blesta's `a.text-dark:hover` group also carries the active tab at (0,5,1)
   with !important, which put near-black text back on the accent tint as soon
   as you hovered it. Mirrored so source order decides. */
.nav .nav-item a.nav-link.active:hover,
.nav .nav-item a.nav-link.active:focus,
.nav .nav-tabs li a.active:hover,
.nav .nav-tabs li.active a:hover,
.nav-tabs .nav li a.active:hover,
.nav-tabs .nav li.active a:hover,
.nav-tabs .nav-item a.nav-link.active:hover,
.nav-tabs li.active > a:hover {
    color: var(--ml-accent-text) !important;
}

/* Inputs and Bootstrap's custom controls. */
.input-group-text {
    background-color: var(--ml-surface-2);
    border-color: var(--ml-border-strong);
    color: var(--ml-muted);
}
.custom-select {
    background-color: var(--ml-surface);
    border-color: var(--ml-border-strong);
    color: var(--ml-ink);
}
.custom-file-label {
    background-color: var(--ml-surface);
    border-color: var(--ml-border-strong);
    color: var(--ml-body);
}
.custom-file-label::after {
    background-color: var(--ml-surface-2);
    color: var(--ml-body);
}
.custom-control-label::before {
    background-color: var(--ml-surface);
    border-color: var(--ml-border-strong);
}
.custom-switch .custom-control-input:checked ~ .custom-control-label::after { background-color: #fff; }
.custom-range::-webkit-slider-runnable-track { background-color: var(--ml-surface-2); }
.custom-range::-moz-range-track { background-color: var(--ml-surface-2); }
.custom-select:disabled,
.custom-control-input[disabled] ~ .custom-control-label::before,
.custom-control-input:disabled ~ .custom-control-label::before,
.custom-file-input[disabled] ~ .custom-file-label,
.custom-file-input:disabled ~ .custom-file-label { background-color: var(--ml-surface-2); }

/* Utilities and remaining components. */
.bg-white { background-color: var(--ml-surface) !important; }
.border, .border-top, .border-right, .border-bottom, .border-left { border-color: var(--ml-border) !important; }
.border-light, .border-white { border-color: var(--ml-border) !important; }
.breadcrumb, .jumbotron { background-color: var(--ml-surface-2); }
.breadcrumb-item.active { color: var(--ml-muted); }
.img-thumbnail { background-color: var(--ml-surface); border-color: var(--ml-border); }
.popover { background-color: var(--ml-surface); border-color: var(--ml-border); }
.bs-popover-top > .arrow::after,
.bs-popover-auto[x-placement^="top"] > .arrow::after { border-top-color: var(--ml-surface); }
.bs-popover-bottom > .arrow::after,
.bs-popover-auto[x-placement^="bottom"] > .arrow::after { border-bottom-color: var(--ml-surface); }
.bs-popover-left > .arrow::after,
.bs-popover-auto[x-placement^="left"] > .arrow::after { border-left-color: var(--ml-surface); }
.bs-popover-right > .arrow::after,
.bs-popover-auto[x-placement^="right"] > .arrow::after { border-right-color: var(--ml-surface); }
.toast, .toast-header { background-color: var(--ml-surface); color: var(--ml-body); }
/* Blesta emits every help tooltip as an inline <a> holding an icon glyph. The
   glyph's ink is not centred in its em box, so box alignment - middle,
   baseline, text-bottom - all leave it hanging 1.5 to 3.5px below the words it
   annotates. Measured against the rendered ink: middle puts the two optical
   centres level beside an ordinary label, which is nearly every field. The
   quantity layout above needs a different value and states its own. */
a[data-toggle="tooltip"] { vertical-align: middle; }

.tooltip-inner { background-color: var(--ml-ink); color: var(--ml-canvas); }
.dropdown-item.active, .dropdown-item:active,
.dropdown-menu li > a.active, .dropdown-menu li > a:active,
ul.dropdown-menu li a.active, ul.dropdown-menu li a:active {
    background-color: var(--ml-accent-bg) !important;
    color: var(--ml-accent-text) !important;
}
.list-group-item-action:active,
a.list-group-item:active { background-color: var(--ml-surface-3); }
.page-item.disabled .page-link {
    background-color: var(--ml-surface);
    border-color: var(--ml-border);
    color: var(--ml-faint);
}
.table .thead-light th {
    background-color: var(--ml-surface-2);
    border-color: var(--ml-border);
    color: var(--ml-muted);
}
.table-bordered, .table-bordered th, .table-bordered td { border-color: var(--ml-border) !important; }
.table tbody + tbody { border-top-color: var(--ml-border); }
.table.multi_heading .email_header { background-color: var(--ml-surface-2); }
.card-body h4 { border-bottom: 0; padding-bottom: 0; }
.carousel-indicators li { background-color: var(--ml-border-strong); }

/* Date picker. */
.datepicker {
    background-color: var(--ml-surface);
    border-color: var(--ml-border);
    color: var(--ml-body);
}
.datepicker table tr td.day:hover,
.datepicker table tr td.focused,
.datepicker table tr td span:hover,
.datepicker table tr td span.focused,
.datepicker .datepicker-switch:hover,
.datepicker .prev:hover,
.datepicker .next:hover,
.datepicker tfoot tr th:hover { background-color: var(--ml-surface-2) !important; }
.datepicker table tr td.range,
.datepicker table tr td.range.disabled,
.datepicker table tr td.range.disabled:hover { background-color: var(--ml-surface-2); }
.datepicker table tr td.active,
.datepicker-days .day.active {
    background-color: var(--ml-accent-solid) !important;
    background-image: none !important;
    color: #fff !important;
}
.datepicker-dropdown::after { border-bottom-color: var(--ml-surface); }
.datepicker-dropdown.datepicker-orient-top::after { border-top-color: var(--ml-surface); }

/* --------------------------------------------------------------- misc --- */
.panel-fix, .no-nav { background: transparent; }
.subtable { background: transparent; }
.loading_container {
    background-color: var(--ml-scrim) !important;
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    color: var(--ml-muted);
}
.loading_container .loading_dialog {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    width: auto;
    margin: 0;
}
.loading_container .progress {
    height: 3px;
    background: var(--ml-surface-2);
    border-radius: 0;
    overflow: hidden;
}
.loading_container .progress-bar,
.progress-bar.bg-secondary {
    background-color: var(--ml-accent-ring) !important;
    background-image: none !important;
    width: 35% !important;
    animation: ml-indeterminate 1.15s ease-in-out infinite;
}
@keyframes ml-indeterminate {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(385%); }
}
.pkg-description p { color: var(--ml-body); }
.text-muted { color: var(--ml-faint) !important; }
.text-info { color: var(--ml-accent) !important; }

/* Blesta's own theme.css is not loaded by this theme, so the Look and Feel
   colour pickers do nothing here. These two keep any inline leftovers sane. */
.header, .title, .nav-content { background: transparent !important; }

html {
    scrollbar-width: thin;
    scrollbar-color: var(--ml-border-strong) transparent;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
    background-color: var(--ml-border-strong);
    border-radius: var(--ml-r-pill);
    /* Transparent border plus content-box clipping insets the thumb without
       painting the container's colour, which was wrong inside cards. */
    border: 2px solid transparent;
    background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--ml-faint); }

/* ----------------------------------------------------------- responsive -- */
@media (max-width: 991px) {
    :root { --ml-pad: 16px; }

    .ml-burger { display: flex; }

    .ml-nav {
        display: none;
        position: absolute;
        top: var(--ml-bar-h);
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 0.75rem var(--ml-pad) 1rem;
        background: var(--ml-canvas);
        border-bottom: 1px solid var(--ml-border);
        max-height: calc(100vh - var(--ml-bar-h));
        overflow-y: auto;
    }
    .ml-nav.is-open { display: flex; }

    .ml-nav-list,
    .ml-nav > .ml-nav-list:first-child {
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        background: none;
        border: 0;
        border-radius: 0;
        padding: 0;
        overflow: visible;
    }
    .ml-nav-end { margin: 0.5rem 0 0; padding-top: 0.75rem; border-top: 1px solid var(--ml-border); }
    .ml-nav-link { border-radius: var(--ml-r); padding: 0.6rem 0.75rem; font-size: 0.875rem; }
    .ml-nav-end .ml-nav-link { border-color: transparent; }
    .ml-account-name { max-width: none; }
    .ml-cta { justify-content: center; }

    .ml-menu {
        position: static;
        display: none;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: none;
        transition: none;
        box-shadow: none;
        border: 0;
        border-radius: 0;
        padding: 0 0 0 1.5rem;
        min-width: 0;
    }
    .ml-menu::before { display: none; }
    .ml-has-menu.is-open > .ml-menu { display: block; }

    .ml-foot-top { grid-template-columns: 1fr 1fr; gap: 2rem; }
    .ml-foot-brand { grid-column: 1 / -1; }
}

@media (max-width: 767px) {
    /* Four stacked stat tiles push the real content off screen. */
    .cards > [class*="col-"] { flex: 0 0 50%; max-width: 50%; }
    .cards .card .card-content { padding: 0.875rem; }
    .cards .card .card-content .card-value { font-size: 1.375rem; }

    .ml-pagehead { padding: 1.5rem 0 1.25rem; }
    .ml-pagehead h1 { font-size: 1.375rem; }
    main.ml-shell { padding-top: 1.25rem; }
    .card { border-radius: var(--ml-r-lg); }
    .card-blesta, .panel-blesta { border-radius: var(--ml-r-lg) !important; }
    .ml-foot-legal { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

@media print {
    .ml-bar, .ml-foot, .ml-pagehead::after, .ml-skip { display: none !important; }
    body { background: #fff; }
    .card, .panel { border-color: #ccc; }
}

@media (prefers-reduced-motion: reduce) {
    .loading_container .progress-bar {
        width: 100% !important;
        animation: none !important;
        transform: none !important;
    }
}

/* ------------------------------------------------ support manager: kb --
   plugins/support_manager/.../css/kb.css is injected through $custom_head,
   which structure.pdt emits after this file, so equal-specificity rules of
   ours would lose. Every selector here carries an extra `html` to win.

   Its `.section-title h3` paints from Bootstrap's own --dark custom property,
   which is #343a40, so the Knowledge Base headings rendered near-black on the
   dark canvas. */
/* Affiliate signup is a single card of prose running the full 1200px, which
   left its centred call to action stranded under 110-character lines. Same
   measure as a KB article. */
html #affiliates { max-width: 860px; }

/* Blesta's application.css carries a blanket `.card p { margin-bottom: 0 }`,
   which is fine for a card holding one paragraph and turns four into an
   unreadable block. Restored here only, rather than globally, since that rule
   is deliberate for the rest of the portal. The button sits in its own
   `p.text-center`, so it is excluded. */
html #affiliates .card-body p:not(.text-center) { margin-bottom: 1rem; }
html #affiliates .card-body ul { margin: 0 0 1rem; padding-left: 1.25rem; }
html #affiliates .card-body li { margin-bottom: 0.375rem; }
html #affiliates .card-body p.text-center { margin: 1.5rem 0 0; }
html #affiliates .card-body .btn {
    padding: 0.625rem 1.5rem;
    font-size: 0.9375rem;
}

/* kb.css is of its era: a 40px centred card around one input, italic
   subtitles pulled up by -10px, a breadcrumb pulled up by -23px to hang off
   the card above it, 5px stacking margins and a FontAwesome glyph in front of
   every row. It loads after this file, so each rule below carries the html
   prefix to win on specificity rather than order. The aim is the card, border
   and hover language already used elsewhere in this theme, not a new one. */

/* Search: the field is the control, so drop the card wrapped around it. */
html .card-kb {
    background-color: transparent;
    border: 0;
    padding: 0;
    margin-bottom: 1rem;
    font-size: 1rem;
    text-align: left;
}
html .card-kb .form-control {
    height: auto;
    padding: 0.625rem 0.875rem;
    background-color: var(--ml-surface-2);
    border: 1px solid var(--ml-border);
    color: var(--ml-ink);
}
html .card-kb .form-control:focus {
    border-color: var(--ml-go, #048c3c);
    box-shadow: none;
}
html .card-kb .btn { padding: 0.625rem 1.125rem; }
html .card-kb .table > thead > tr > th { border-bottom: 2px solid var(--ml-hairline); }

/* No longer hanging off the bottom of a slab, so it needs its own spacing. */
html .card-kb + nav .breadcrumb { margin-top: 0; margin-bottom: 1.75rem; }

html .section-title { margin-bottom: 0.875rem; }
html .section-title h3 {
    font-family: var(--ml-display, inherit);
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--ml-ink);
    margin-bottom: 0.25rem;
}
html .section-title p {
    margin-top: 0;
    margin-bottom: 0;
    font-style: normal;
    font-size: 0.9375rem;
    color: var(--ml-muted);
}
/* .section-title is a section label on the index and category pages
   ("Categories", "Articles") but the article's own title on an article page,
   where it was rendering smaller than the h2s inside the body it introduces.
   The adjacent .article is what tells the two apart. */
html .section-title:has(+ .article) h3 {
    font-size: 1.75rem;
    line-height: 1.2;
    margin-bottom: 0.75rem;
}
/* Constrain the whole article page to one readable measure, not just the
   prose, so the search field, breadcrumb, title, body and rating block all
   share an edge. Narrowing .article alone left everything above it running
   the full width with a void down the right. The index and category pages
   keep the full width, because the card grid wants it. */
html .col-md-12:has(> .article) { max-width: 840px; }
html .article { margin-top: 0; }
html .article h2 {
    font-family: var(--ml-display, inherit);
    font-size: 1.25rem;
    font-weight: 700;
    margin: 1.75rem 0 0.5rem;
}
html .article h3 { font-size: 1.0625rem; font-weight: 700; margin: 1.5rem 0 0.5rem; }
html .article p { margin-bottom: 0.875rem; }
html .article ul, html .article ol { margin-bottom: 1rem; padding-left: 1.25rem; }
html .article li { margin-bottom: 0.35rem; }
html .article li > p { margin-bottom: 0.35rem; }

/* A folder glyph in front of every folder and a page glyph in front of every
   page is decoration that repeats what the text already says. */
html .section-title h3 > i,
html .categories i.fas { display: none; }

/* Category cards and article rows share one treatment, matching the order
   form cards: surface, hairline border, and the border picking up the brand
   on hover rather than the whole tile changing. */
html .categories .row { margin-left: -0.4rem; margin-right: -0.4rem; }
html .categories [class^="col-"],
html .categories [class*=" col-"] { padding: 0.4rem; }
html .categories div { margin-bottom: 0; }
html .categories .bg-light {
    height: 100%;
    background-color: var(--ml-surface-2) !important;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    padding: 1rem 1.125rem !important;
    transition: border-color 0.15s ease, transform 0.15s ease;
}
html .categories .bg-light:hover {
    border-color: var(--ml-go, #048c3c);
    transform: translateY(-1px);
}
html .categories a {
    font-family: var(--ml-display, inherit);
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ml-ink);
}
html .categories a:hover { color: var(--ml-go, #048c3c); text-decoration: none; }
html .categories p {
    margin: 0.375rem 0 0;
    font-size: 0.875rem;
    color: var(--ml-muted);
}
/* The article rating block. kb.css loads after this file, so every rule here
   carries the html prefix to win on specificity rather than order.

   Core drops .rate straight into a .row with no column around it, so it was a
   shrink-to-fit flex item: 452px wide and sitting 10px left of the article it
   belongs to. Filling the row and insetting by the 10px gutter puts its edges
   exactly on the article's. */
html .row > .rate {
    flex: 1 1 auto;
    min-width: 0;
    margin-left: 10px;
    margin-right: 10px;
}
html .rate {
    background-color: var(--ml-surface-2);
    border-radius: var(--ml-r);
    padding: 1.25rem;
    font-size: 1rem;
}
html .rate h5 {
    font-family: var(--ml-display, inherit);
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--ml-ink);
    margin: 0 0 0.875rem;
}
/* kb.css gives these padding: 0 4px, which turns a btn-lg into a 44px chip. */
html .rate p { display: flex; flex-wrap: wrap; gap: 0.5rem; }
html .rate a.btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-right: 0;
    padding: 0.5rem 1rem;
    font-size: 0.9375rem;
    line-height: 1.2;
    background-color: var(--ml-surface);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
html .rate a.btn:hover { border-color: currentColor; }
html .rate a.green, html .rate a.green:hover { color: var(--ml-ok); }
html .rate a.red, html .rate a.red:hover { color: var(--ml-bad-text); }
html .rate p.voted { font-size: 0.9375rem; color: var(--ml-muted); margin-top: 0.5rem; }

/* Knowledge Base breadcrumb. Scoped to the KB so the slab treatment the rest
   of the portal uses is left alone: here it sits directly under the search
   card, and two stacked panels for one line of navigation is too much. */
html .card-kb + nav .breadcrumb {
    background-color: transparent;
    border: 0;
    padding-left: 0;
    padding-right: 0;
}
html .card-kb + nav .breadcrumb-item a { color: var(--ml-muted); }
html .card-kb + nav .breadcrumb-item a:hover { color: var(--ml-ink); }

/* ------------------------------------------------------------- altcha --
   The ALTCHA widget colours itself with light-dark(), which follows the
   used color-scheme rather than our data-theme attribute. Without this it
   renders a white card on the dark page. Scoped to the widget so no native
   control anywhere else changes behaviour. */
/* Two caps kept the widget narrower than the fields around it: its own
   --altcha-max-width of 320px, and Blesta's .captcha { max-width: 350px }
   from application.css, meant for the fixed size internal captcha image.
   Replaced with one cap wider than the login card, so the widget fills the
   width there and still cannot stretch across the order form, where the
   fields run the full page width. */
/* --altcha-max-width is lifted inline by the captcha provider, so it applies
   in the admin theme too. Only the ceiling is a theme decision. */
.captcha.captcha-altcha { max-width: 26rem; }

html[data-theme="dark"] .altcha { color-scheme: dark; }

/* --------------------------------------- editor and file attachments --
   The ticket form ships two third-party widgets that paint their own
   surfaces white and read none of our variables: Dropzone colours the
   whole <form>, and TOAST UI colours its editing area, its mode switch
   and the tabs in it. On the dark theme that is a white page with dark
   inputs floating on it, which is what the Open Ticket form looked like.

   Each surface is restated rather than blanket-overridden, so a widget
   update that adds a part shows up as an unstyled part rather than as a
   silently broken theme. */

/* Dropzone makes the entire form the drop target, so this is the page
   background, not a panel */
form.dropzone,
.dropzone { background: transparent; }

.dropzone .dz-message,
.dropzone .dz-default { color: var(--ml-muted); }

.dropzone .dz-preview .dz-image,
.dropzone .dz-preview .dz-details {
    background: var(--ml-surface-2);
    color: var(--ml-ink);
}

/* The editor: writing surface, then the chrome around it */
.toastui-editor-defaultUI,
.toastui-editor-ww-container,
.toastui-editor-md-container,
.toastui-editor-md-container .toastui-editor,
.toastui-editor-md-preview {
    background: var(--ml-surface-2);
    color: var(--ml-ink);
}

.toastui-editor-contents,
.toastui-editor-contents p,
.toastui-editor-md-preview .toastui-editor-contents { color: var(--ml-ink); }

.toastui-editor-defaultUI-toolbar {
    background: var(--ml-surface-3);
    border-bottom: 1px solid var(--ml-hairline);
}
.toastui-editor-defaultUI { border: 1px solid var(--ml-border); }

/* The Markdown / WYSIWYG switch sits at the foot of the editor */
.toastui-editor-mode-switch {
    background: var(--ml-surface-3);
    border-top: 1px solid var(--ml-hairline);
}
.toastui-editor-mode-switch .tab-item {
    background: transparent;
    border-color: var(--ml-hairline);
    color: var(--ml-muted);
}
.toastui-editor-mode-switch .tab-item.active {
    background: var(--ml-surface);
    color: var(--ml-ink);
}

/* Blesta emits the captcha in a bare Bootstrap column while the fields
   above it sit directly in the form, so its 10px gutter left it a step
   right of everything else on the ticket form. Matched by containing the
   captcha *directly*, which is that form's shape - the signup form nests
   it inside a .form-group and keeps its gutter. */
.col-md-12:has(> .captcha),
.col-sm-12:has(> .captcha) {
    padding-left: 0;
    padding-right: 0;
}

/* ------------------------------------------------ department chooser --
   The support manager renders departments as list-group anchors in two
   columns. The markup belongs to the plugin, so this is CSS only: the job
   is to make them read as a choice rather than as a bulleted list -
   matched heights, a hover state on the whole tile, and something to aim
   at on the right. */
#client_tickets .card-body > .row { align-items: stretch; }
#client_tickets .card-body > .row > [class^="col-"],
#client_tickets .card-body > .row > [class*=" col-"] { display: flex; }
#client_tickets .list-group { width: 100%; }

#client_tickets .list-group-item {
    position: relative;
    height: 100%;
    background: var(--ml-surface-2);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

#client_tickets .list-group-item:hover,
#client_tickets .list-group-item:focus {
    border-color: var(--ml-go, #048c3c);
    box-shadow: 0 0 0 1px var(--ml-go, #048c3c);
    transform: translateY(-1px);
    text-decoration: none;
}

/* The room for the chevron is taken from the content rather than by
   padding the tile: the markup carries Bootstrap's p-3, whose !important
   beats any padding set here. */
#client_tickets .list-group-item h4,
#client_tickets .list-group-item p { margin-right: 1.75rem; }

#client_tickets .list-group-item h4 { color: var(--ml-ink); }
#client_tickets .list-group-item p {
    color: var(--ml-muted);
    margin-bottom: 0;
}

/* A literal chevron rather than a Font Awesome glyph: no dependency on the
   icon font having loaded, and nothing to go wrong if it is swapped out. */
#client_tickets .list-group-item::after {
    content: "\203A";
    position: absolute;
    top: 50%;
    right: 1.125rem;
    transform: translateY(-50%);
    font-size: 1.5rem;
    line-height: 1;
    color: var(--ml-muted);
    transition: color 0.15s ease, right 0.15s ease;
}
#client_tickets .list-group-item:hover::after {
    color: var(--ml-go, #048c3c);
    right: 0.875rem;
}

/* ------------------------------------------------------- order forms --
   /order/forms lists what can be ordered. Core renders each entry as a
   full-width bar with the button off to the right, which at three entries
   is three horizontal rules and a lot of empty middle. The markup belongs
   to the order plugin, so this is CSS only: turn the bars into a grid of
   equal cards that read as a choice, the same shape as the package group
   chooser a step later.

   Specificity beats the Bootstrap column it carries (two classes to one),
   and media queries add none, so the widths below are the whole story. */
.col-lg-12.order-listing {
    flex: 0 0 100%;
    max-width: 100%;
    display: flex;
    margin-bottom: 1.5rem;
}

@media (min-width: 768px) {
    .col-lg-12.order-listing { flex: 0 0 50%; max-width: 50%; }
}

@media (min-width: 1200px) {
    .col-lg-12.order-listing { flex: 0 0 33.3333%; max-width: 33.3333%; }
}

.order-listing .card {
    width: 100%;
    background: var(--ml-surface-2);
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.order-listing .card:hover,
.order-listing .card:focus-within {
    border-color: var(--ml-go, #048c3c);
    box-shadow: 0 0 0 1px var(--ml-go, #048c3c);
    transform: translateY(-1px);
}

/* The inner row is a 9/3 split built for a wide bar. Stacked, each column
   fills the card, and the order puts the button last where it belongs:
   core emits it second, between the name and the description. */
.order-listing .card > .row { flex-direction: column; }

/* Turning the row into a column moves flex-basis onto the vertical axis,
   but max-width keeps constraining the horizontal one, so col-sm-3 stayed
   a quarter wide and squeezed the button into a 66px sliver. */
.order-listing .card > .row > [class^="col-"],
.order-listing .card > .row > [class*=" col-"] {
    flex: 0 0 auto;
    width: 100%;
    max-width: 100%;
    /* The row's gutter is 10px (its margin is -10px), but the name and button
       columns also carry col-xs-12, a Bootstrap 3 class still defined at the
       old 15px gutter. That put the heading and the button 5px right of the
       description. Measured: h3 at 200, description at 195. */
    padding-left: 10px;
    padding-right: 10px;
}
.order-listing .card > .row > .col-sm-9 { order: 1; }
.order-listing .card > .row > .col-sm-12 { order: 2; }
.order-listing .card > .row > .col-sm-3 { order: 3; }
.order-listing .card > .row > a { order: 4; }
/* Floats have nothing to clear once the row is a column */
.order-listing .card > .row > .clearfix { display: none; }

.order-listing h3 {
    font-family: var(--ml-display, inherit);
    font-weight: 700;
    font-size: 1.25rem;
    margin: 0 0 0.75rem;
    color: var(--ml-ink);
}

/* Pushed against the button so cards of unequal description length still
   line their buttons up */
.order-listing .card > .row > .col-sm-12 {
    color: var(--ml-muted);
    margin-bottom: auto;
    padding-bottom: 1rem;
}
.order-listing .card > .row > .col-sm-12 p:last-child { margin-bottom: 0; }

/* One full-width action per card. Core ships two, showing whichever the
   breakpoint calls for, and both become blocks here. */
.order-listing .btn-success { display: block; width: 100%; }

/* ── Checkout: client_pay_method.pdt ─────────────────────────────────────
   How to pay on the left, what is paid on the right. Core's fields and ids
   are untouched; this only lays them out. */
.ml-checkout-section { margin-bottom: 1.5rem; }
.ml-checkout-label {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--ml-muted);
}
.ml-checkout-option {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0 0 0.5rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
    color: var(--ml-ink);
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
.ml-checkout-option:hover { border-color: var(--ml-border-strong); }
.ml-checkout-option:has(input:checked) {
    border-color: var(--ml-accent);
    box-shadow: 0 0 0 3px var(--ml-accent-ring);
}
.ml-checkout-option input { margin: 0; flex: none; }
.ml-checkout-summary {
    position: sticky;
    top: 1rem;
    padding: 1.25rem;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    background: var(--ml-surface-3);
}
.ml-checkout-lines { list-style: none; margin: 0 0 1rem; padding: 0; }
.ml-checkout-lines li {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--ml-hairline);
    color: var(--ml-ink);
}
.ml-checkout-context { display: block; font-size: 0.8rem; color: var(--ml-muted); }
.ml-checkout-amount { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ml-checkout-totals {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.25rem 1rem;
    margin: 0 0 0.75rem;
    color: var(--ml-muted);
}
.ml-checkout-totals dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.ml-checkout-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    color: var(--ml-ink);
}
.ml-checkout-total strong {
    font-family: var(--ml-display);
    font-size: 1.75rem;
    font-variant-numeric: tabular-nums;
}
.ml-checkout-credit { margin-top: 1rem; font-size: 0.9rem; }

/* ── Dashboard: melonslab_dashboard plugin ───────────────────────────────
   The attention strip above the tiles and the Servers section below them.
   The expand chevrons on service rows are dropped; the row still opens. */
tr.expand td:last-of-type::after { content: none; }

.ml-attention { display: grid; gap: 0.5rem; margin-bottom: 1.25rem; }
.ml-attention-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--ml-border);
    border-left-width: 4px;
    border-radius: var(--ml-r);
    background: var(--ml-surface);
    color: var(--ml-ink);
}
.ml-attention-item:hover { text-decoration: none; border-color: var(--ml-border-strong); color: var(--ml-ink); }
.ml-attention-item > span { flex: 1; }
.ml-attention-go { font-size: 0.75rem; color: var(--ml-faint); }
.ml-attention-danger { border-left-color: #dc3545; }
.ml-attention-danger > .fas:first-child { color: #dc3545; }
.ml-attention-warning { border-left-color: #f0ad4e; }
.ml-attention-warning > .fas:first-child { color: #f0ad4e; }
.ml-attention-success { border-left-color: var(--ml-go); }
.ml-attention-success > .fas:first-child { color: var(--ml-go); }
.ml-attention-secondary { border-left-color: var(--ml-border-strong); }

.ml-server {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    height: 100%;
    padding: 1rem 1.1rem;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-lg);
    background: var(--ml-surface);
    color: var(--ml-ink);
    transition: border-color 0.12s ease;
}
.ml-server:hover { text-decoration: none; color: var(--ml-ink); border-color: var(--ml-border-strong); }
.ml-server-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.ml-server-name { font-family: var(--ml-display); font-size: 1.05rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-server-meta { font-size: 0.85rem; color: var(--ml-muted); }
.ml-server-traffic { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.2rem; }
.ml-server-traffic .progress { display: block; height: 0.4rem; }
.ml-server-traffic .progress-bar { display: block; height: 100%; }
.ml-server-foot { display: flex; justify-content: space-between; align-items: center; margin-top: auto; padding-top: 0.4rem; }
.ml-server-manage { font-size: 0.85rem; font-weight: 600; color: var(--ml-accent-text); }

/* Tiles in a row share one height, however their labels wrap. A tile is
   col > a > .card, or col > a > div#id > .card for the html cards. */
.right_content .cards > [class*="col-"] { display: flex; margin-bottom: 1.25rem; }
.right_content .cards > [class*="col-"] > a,
.right_content .cards > [class*="col-"] > a > div:not(.card) { display: flex; flex: 1 1 auto; min-width: 0; }
.right_content .cards .card { flex: 1 1 auto; width: 100%; margin-bottom: 0; }
/* A word set where a figure goes ("Nothing due") would outsize the figures */
.cards .card .card-content .card-value.ml-card-text { font-size: 1.375rem; line-height: 1.36; }

/* Dashboard Domains section: a row per domain, its expiry on the right */
.ml-section-link { float: right; font-size: 0.85rem; font-weight: 600; color: var(--ml-accent-text); }
.ml-domain-list { display: grid; gap: 0.5rem; }
.ml-domain {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
    background: var(--ml-surface);
    color: var(--ml-ink);
}
.ml-domain:hover { text-decoration: none; color: var(--ml-ink); border-color: var(--ml-border-strong); }
.ml-domain-main { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.ml-domain-name { font-family: var(--ml-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-expiry {
    flex: none;
    padding: 0.2rem 0.6rem;
    border-radius: var(--ml-r-pill);
    font-size: 0.8rem;
    white-space: nowrap;
    color: var(--ml-muted);
    background: var(--ml-surface-2);
}
.ml-expiry-warning { color: #8a5a00; background: rgb(240 173 78 / 0.18); }
.ml-expiry-danger { color: #b02a37; background: rgb(220 53 69 / 0.15); }
html[data-theme="dark"] .ml-expiry-warning { color: #f0c36d; }
html[data-theme="dark"] .ml-expiry-danger { color: #f08a94; }

/* Dashboard icons: one per kind of thing, the same wherever it appears.
   Tiles get theirs by card id, so other plugins' tiles match without
   touching them. */
.cards .card .card-content::before {
    display: block;
    margin-bottom: 0.6rem;
    content: "";
    line-height: 1;
}
/* The box is ::before, the Lucide icon ::after, both in the first grid
   column; a tile names its icon in --ml-tile-icon */
#melonslab_dashboard_get_amount_due .card-content { --ml-tile-icon: var(--ml-i-receipt-euro); }
#melonslab_dashboard_get_next_renewal .card-content { --ml-tile-icon: var(--ml-i-refresh-cw); }
#domains_get_domain_count .card-content { --ml-tile-icon: var(--ml-i-globe); }
#support_manager_get_open_tickets_count .card-content { --ml-tile-icon: var(--ml-i-ticket); }
#client_cards_get_services_count .card-content { --ml-tile-icon: var(--ml-i-server); }
#client_cards_get_invoices_count .card-content { --ml-tile-icon: var(--ml-i-receipt-euro); }

.ml-head-icon { margin-right: 0.35rem; color: var(--ml-faint); }
.ml-item-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: var(--ml-r);
    background: var(--ml-surface-2);
    color: var(--ml-muted);
    font-size: 0.85rem;
}
.ml-server-head { justify-content: flex-start; }
.ml-server-head .badge { margin-left: auto; }

/* Melon green, the secondary brand colour, as the landing site uses it:
   icons sit on a soft melon tile (bg-melon-50/950, border melon-100/900,
   icon melon-600/400), and good news reads in melon. Brand red stays for
   where you are and what you click. The --ml-ok set is that palette. */
.ml-item-icon,
.cards .card .card-content::before {
    background: var(--ml-ok-bg);
    border: 1px solid var(--ml-ok-line);
    color: var(--ml-ok-text);
}
.cards .card .card-content::before {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--ml-r);
    font-size: 0.85rem;
}
.ml-head-icon { color: var(--ml-ok-text); }
/* "Nothing due" is good news */
#melonslab_dashboard_get_amount_due .card-value.ml-card-text { color: var(--ml-ok-text); }
/* A domain with more than a month left stays grey (the .ml-expiry default),
   so a coloured badge always means there is something to do */

/* Tiles: the icon beside the figure rather than above it, which halves their
   height, and rounded like the sections below. Blesta forces a small radius
   and centred text on tiles with !important, so these have to as well. */
.cards .card { border-radius: var(--ml-r-xl) !important; text-align: left !important; }
.cards .card .card-content {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 0.875rem;
    align-items: center;
    padding: 1rem 1.125rem;
}
.cards .card .card-content::before { grid-column: 1; grid-row: 1 / span 2; margin-bottom: 0; width: 2.5rem; height: 2.5rem; font-size: 1rem; }
.cards .card .card-content .card-value,
.cards .card .card-content .card-label { grid-column: 2; margin: 0; }
.cards .card .card-content .card-value { font-size: 1.625rem; }
.cards .card .card-content .card-value.ml-card-text { font-size: 1.25rem; line-height: 1.3; }
/* No open tickets: the tile offers help instead of a zero */
#support_manager_get_open_tickets_count.ml-card-help .card-content { --ml-tile-icon: var(--ml-i-life-buoy); }
.cards .card .card-content::after {
    content: "";
    grid-column: 1;
    grid-row: 1 / span 2;
    justify-self: center;
    align-self: center;
    width: 1.15rem;
    height: 1.15rem;
    background-color: var(--ml-ok-text);
    -webkit-mask: var(--ml-tile-icon, none) no-repeat center / contain;
    mask: var(--ml-tile-icon, none) no-repeat center / contain;
}

/* Section headers: how many, and a way to the full list */
.ml-count {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.5rem;
    border-radius: var(--ml-r-pill);
    background: var(--ml-surface-2);
    color: var(--ml-muted);
    font-size: 0.75rem;
    font-weight: 600;
    vertical-align: 0.1em;
}
/* Service sidebar: the icons are melon, the open tab keeps brand red */
.list-group:not(.list-options) > .list-group-item:not(.active) > i:first-child { color: var(--ml-ok-text); }

/* Server power state on the dashboard cards: grey while asking, then
   melon when running, neutral when stopped, amber when there is no answer */
.ml-power { display: inline-flex; align-items: center; margin-left: auto; font-size: 1.1rem; line-height: 1; color: var(--ml-faint); }
/* A shape per state, so it reads without colour too: a spinner while
   asking, a play button running, a stop button stopped, a question mark
   with no answer. The word stays for screen readers and as the tooltip. */
.ml-power { --ml-power-i: var(--ml-i-loader-circle); }
.ml-power-dot::before {
    content: "";
    display: inline-block;
    width: 1.15em;
    height: 1.15em;
    background-color: currentColor;
    -webkit-mask: var(--ml-power-i) no-repeat center / contain;
    mask: var(--ml-power-i) no-repeat center / contain;
}
.ml-power:not([class*="is-"]) .ml-power-dot::before { animation: ml-power-spin 0.9s linear infinite; }
.ml-power.is-running { color: var(--ml-ok); }
.ml-power.is-running { --ml-power-i: var(--ml-i-circle-play); }
.ml-power.is-stopped { color: var(--ml-bad-text); }
.ml-power.is-stopped { --ml-power-i: var(--ml-i-circle-stop); }
.ml-power.is-unknown { color: var(--ml-warn); }
.ml-power.is-unknown { --ml-power-i: var(--ml-i-circle-help); }
.ml-power-text { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
@keyframes ml-power-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ml-power .ml-power-dot::before { animation: none !important; } }

/* ── Service information (client_services_service_infobox.pdt) ───────────
   Name and state, four key facts, options as a list, actions in a row with
   cancelling quiet at the end. */
.ml-svc-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem; }
.ml-svc-title h3 { margin: 0; font-family: var(--ml-display); font-size: 1.5rem; color: var(--ml-ink); word-break: break-word; }
.ml-svc-sub { color: var(--ml-muted); font-size: 0.9rem; }
.ml-svc-state { display: flex; align-items: center; gap: 0.75rem; }
.ml-svc-state .ml-power { margin-left: 0; }
.ml-svc-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.75rem; margin-bottom: 1.5rem; }
@media (max-width: 767.98px) { .ml-svc-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ml-svc-fact {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r);
    background: var(--ml-surface-3);
}
.ml-svc-label { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; color: var(--ml-muted); }
.ml-svc-value { font-size: 1.05rem; font-weight: 600; color: var(--ml-ink); font-variant-numeric: tabular-nums; }
.ml-svc-value small { display: block; font-size: 0.8rem; font-weight: 400; color: var(--ml-muted); }
.ml-svc-coupon { color: var(--ml-ok-text); margin-bottom: 1.5rem; }
.ml-svc-heading { font-size: 1rem; font-weight: 600; color: var(--ml-ink); margin: 0 0 0.75rem; }
.ml-svc-options { list-style: none; margin: 0 0 1.5rem; padding: 0; border: 1px solid var(--ml-border); border-radius: var(--ml-r); }
.ml-svc-options li {
    display: grid;
    /* A fixed price column: each row is its own grid, so an "auto" one was
       as wide as that row's price, and an option without one shifted left */
    grid-template-columns: minmax(0, 2fr) minmax(0, 2fr) 7rem;
    gap: 1rem;
    align-items: baseline;
    padding: 0.7rem 1rem;
    border-top: 1px solid var(--ml-hairline);
}
.ml-svc-options li:first-child { border-top: 0; }
.ml-svc-option-name { color: var(--ml-muted); }
.ml-svc-option-value { color: var(--ml-ink); font-weight: 500; }
.ml-svc-option-price { color: var(--ml-muted); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.ml-svc-option-note { display: block; font-size: 0.8rem; font-weight: 400; color: var(--ml-muted); }
.ml-svc-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.ml-svc-cancel { margin-left: auto; font-size: 0.875rem; color: var(--ml-bad-text, #b02a37); }
.ml-svc-cancel:hover { color: var(--ml-bad-text, #b02a37); text-decoration: underline; }

/* A suspended service: why, and the way back */
.ml-svc-suspended {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--ml-bad-line, #f1aeb5);
    border-radius: var(--ml-r);
    background: var(--ml-bad-bg);
    color: var(--ml-bad-text, #b02a37);
}
.ml-svc-suspended > span { flex: 1; }
.ml-svc-suspended > .btn { flex: none; }

/* Affiliate overview (Order plugin): Bootstrap's solid green, teal and amber
   boxes with pale text become tiles like the dashboard's, the figure in ink
   and the labels muted. The referral link field follows the theme too. */
html .affiliate_boxes .card {
    background: var(--ml-surface) !important;
    border: 1px solid var(--ml-border);
    border-radius: var(--ml-r-xl);
    color: var(--ml-ink);
    padding: 1.25rem;
    margin-bottom: 1.25rem;
    text-align: center;
}
html .affiliate_boxes .card p { margin: 0; color: var(--ml-muted); font-size: 0.85rem; }
html .affiliate_boxes .card h2 {
    margin: 0.35rem 0;
    font-family: var(--ml-display);
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--ml-ink);
    font-variant-numeric: tabular-nums;
}
html .affiliate_boxes .card::before {
    content: "";
    display: block;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0 auto 0.6rem;
    background-color: var(--ml-ok-text);
    -webkit-mask: var(--ml-aff-icon) no-repeat center / contain;
    mask: var(--ml-aff-icon) no-repeat center / contain;
}
html .affiliate_boxes .card.bg-success { --ml-aff-icon: var(--ml-i-mouse-pointer-click); }
html .affiliate_boxes .card.bg-info { --ml-aff-icon: var(--ml-i-shopping-cart); }
html .affiliate_boxes .card.bg-warning { --ml-aff-icon: var(--ml-i-chart-line); }
html input.form-control.referral_link[readonly] {
    background: var(--ml-surface-2);
    border-color: var(--ml-border);
    color: var(--ml-ink);
    font-family: var(--ml-mono, monospace);
    font-size: 0.875rem;
}

/* Language switch, as on the website: a flag on the button; flag, name and a
   check for the current one in the menu */
.ml-lang { gap: 0.3rem; padding-left: 0.5rem; padding-right: 0.55rem; }
#language_switcher { min-width: 11rem; }
#language_switcher .ml-menu-item { display: flex; align-items: center; gap: 0.6rem; }
#language_switcher .ml-menu-item.is-current { color: var(--ml-accent-text); font-weight: 600; }
.ml-lang-check { margin-left: auto; font-size: 0.85rem; }
