/* VirtFusion Direct Provisioning Module Styles */

/* Typography */
.vf-bold {
    font-weight: 800;
}
.vf-small {
    font-size: 0.9rem;
}

/* Buttons */
.vf-spinner-margin {
    margin-right: 7px;
}

/* Status Badges */
.vf-badge {
    font-size: 0.75rem;
    padding: 0.35rem 0.75rem;
    text-transform: uppercase;
    font-weight: 700;
    border-radius: 6px;
    display: inline-block;
}
.vf-badge-active {
    background-color: rgba(32, 177, 0, 0.12);
    color: #276900;
}
.vf-badge-awaiting {
    background-color: rgba(177, 89, 0, 0.12);
    color: #692000;
}
.vf-badge-suspended {
    background-color: rgba(220, 53, 69, 0.12);
    color: #721c24;
}

/* ---------------- Hero action buttons ----------------
   Two wrong versions preceded this one, and the middle is the point.

   First came Bootstrap contextual fills (btn-warning/info/danger): pale
   washes with low-contrast text that read as DISABLED rather than clickable.
   Correcting that produced the opposite — flat white outlines with a single
   coloured icon — which read as dead.

   What works is a tint: a soft coloured ground with a SATURATED label of the
   same hue. The colour is unmistakably there, the text passes contrast easily
   because it is the strong end of the ramp, and four of them side by side do
   not fight, because saturation lives in the type rather than the fill.

   Width was the other failure. Uppercase, letter-spacing and "Forçar
   Desligamento" spelled out pushed the row past one line; since the power
   buttons appear and vanish with the server's state, the wrap point moved and
   the whole row jumped. Sentence case, a short destructive label, and a fixed
   row height hold it still. */
.vf-power-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
}
.vf-power-buttons .vf-btn-power {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-width: 0;
    height: 36px;
    padding: 0 14px;
    border: 1px solid transparent;
    border-radius: 8px;
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: none;
    letter-spacing: 0;
    white-space: nowrap;
    box-shadow: none;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.1s, box-shadow 0.15s;
}
/* Lifts a hair on hover. Small enough to read as responsiveness rather than
   movement, and the reason the row has a fixed height — otherwise the
   transform would nudge its neighbours. */
.vf-power-buttons .vf-btn-power:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(22, 32, 43, 0.10);
}
.vf-power-buttons .vf-btn-power:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: none;
}
.vf-power-buttons .vf-btn-power:disabled {
    opacity: 0.5;
    cursor: default;
    transform: none;
    box-shadow: none;
}
.vf-btn-power svg { flex-shrink: 0; opacity: 0.9; }

.vf-btn-power-start {
    background: #e6f6ec;
    border-color: #b4e2c6;
    color: #12703b;
}
.vf-btn-power-start:hover:not(:disabled) {
    background: #d5efe0;
    border-color: #93d6ae;
    color: #0d5c30;
}
.vf-btn-power-restart {
    background: #fdf3e0;
    border-color: #f0d7a2;
    color: #8c5406;
}
.vf-btn-power-restart:hover:not(:disabled) {
    background: #fbe9cb;
    border-color: #e7c680;
    color: #744503;
}
.vf-btn-power-shutdown {
    background: #eaf1f9;
    border-color: #c2d6ea;
    color: #2f5378;
}
.vf-btn-power-shutdown:hover:not(:disabled) {
    background: #dbe7f4;
    border-color: #a7c3e0;
    color: #24456b;
}
.vf-btn-power-force {
    background: #fdeceb;
    border-color: #f3c1bc;
    color: #a32b22;
}
.vf-btn-power-force:hover:not(:disabled) {
    background: #fadcd9;
    border-color: #eaa9a2;
    color: #86201a;
}

/* Hidden elements (initial state) */
#vf-login-button-spinner {
    display: none;
}
#vf-password-reset-button-spinner {
    display: none;
}
#vf-password-reset-error {
    display: none;
}
#vf-password-reset-success {
    display: none;
}
#vf-login-error {
    display: none;
}
#vf-server-info {
    display: none;
}
#vf-server-info-error {
    display: none;
    margin: 10px;
}

/* Skeleton Loading */
.vf-skeleton {
    background: linear-gradient(90deg, #e9ecef 25%, #f4f4f4 50%, #e9ecef 75%);
    background-size: 200% 100%;
    animation: vf-skeleton-pulse 1.5s ease-in-out infinite;
    border-radius: 4px;
}
.vf-skeleton-line {
    height: 14px;
    margin-bottom: 10px;
    border-radius: 4px;
}
.vf-skeleton-line-short {
    width: 60%;
}
.vf-skeleton-line-medium {
    width: 80%;
}
@keyframes vf-skeleton-pulse {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Action Progress Banner */
#vf-action-progress {
    background: #337ab7;
    color: #fff;
    padding: 8px 16px;
    border-radius: 6px;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 0.85rem;
}
#vf-action-progress .spinner-border {
    width: 16px;
    height: 16px;
    border-width: 2px;
}

/* Loader */
#vf-server-info-loader {
    min-height: 136px;
}
#vf-loading {
    display: inline-block;
    width: 30px;
    height: 30px;
    border: 3px solid rgba(225, 224, 224, 0.3);
    border-radius: 50%;
    border-top-color: #0e151a;
    animation: vf-spin 1s ease-in-out infinite;
    -webkit-animation: vf-spin 1s ease-in-out infinite;
}
.vf-loader {
    margin: 30px;
}

@keyframes vf-spin {
    to {
        transform: rotate(360deg);
    }
}
@-webkit-keyframes vf-spin {
    to {
        transform: rotate(360deg);
    }
}

/* Network / IP Management */
.vf-ip-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
}
.vf-ip-address {
    font-family: monospace;
    font-size: 0.9rem;
}
/* Backup Timeline */
.vf-timeline {
    position: relative;
    padding-left: 20px;
    border-left: 2px solid #dee2e6;
    margin-left: 8px;
}
.vf-timeline-item {
    position: relative;
    padding: 8px 0 8px 12px;
}
.vf-timeline-dot {
    position: absolute;
    left: -27px;
    top: 12px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid #fff;
}
.vf-timeline-dot-success {
    background: #28a745;
}
.vf-timeline-dot-pending {
    background: #ffc107;
}
.vf-timeline-content {
    font-size: 0.85rem;
}

/* Server Name Dropdown */
#vf-name-dropdown {
    position: relative;
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    margin-top: 4px;
    max-width: 250px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    z-index: 10;
}
.vf-name-option {
    padding: 6px 12px;
    cursor: pointer;
    font-family: monospace;
    font-size: 0.85rem;
    border-bottom: 1px solid #f0f0f0;
}
.vf-name-option:last-child {
    border-bottom: none;
}
.vf-name-option:hover {
    background: rgba(51,122,183,0.06);
}

/* Copy to Clipboard */
.vf-ip-copy {
    padding: 2px 5px;
    line-height: 1;
    color: #6c757d;
    background: none;
    border: 1px solid transparent;
    border-radius: 3px;
    cursor: pointer;
    vertical-align: middle;
}
.vf-ip-copy:hover {
    color: #337ab7;
    background: rgba(51,122,183,0.08);
    border-color: rgba(51,122,183,0.2);
}
.vf-copy-tooltip {
    position: absolute;
    margin-left: 4px;
    padding: 2px 8px;
    font-size: 0.75rem;
    color: #fff;
    background: #28a745;
    border-radius: 3px;
    white-space: nowrap;
    animation: vf-fade-in 0.2s ease;
}
@keyframes vf-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* OS Template Gallery */
.vf-os-category-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    margin-top: 6px;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 700;
    font-size: 0.9rem;
    user-select: none;
    transition: background 0.15s;
}
.vf-os-category:first-child .vf-os-category-header {
    margin-top: 0;
}
.vf-os-category-header:hover {
    background: rgba(0,0,0,0.03);
}
.vf-os-category-icon {
    width: 28px;
    height: 28px;
    min-width: 28px;
    min-height: 28px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
    flex-shrink: 0;
    overflow: hidden;
}
.vf-os-category-icon img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
}
.vf-os-category-arrow {
    margin-left: auto;
    font-size: 0.7rem;
    color: #888;
}
.vf-os-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 0;
    margin-bottom: 4px;
}
.vf-os-card {
    width: 120px;
    border: 2px solid #dee2e6;
    border-radius: 8px;
    padding: 10px 8px;
    text-align: center;
    cursor: pointer;
    overflow: hidden;
    transition: border-color 0.15s, background-color 0.15s, box-shadow 0.15s;
}
.vf-os-card:hover {
    border-color: #337ab7;
}
.vf-os-card-selected {
    border-color: #337ab7;
    background: rgba(51,122,183,0.06);
    box-shadow: 0 0 0 1px rgba(51,122,183,0.3);
}
.vf-os-card-eol {
    opacity: 0.6;
}
.vf-os-icon {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    margin: 0 auto 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    font-size: 1.1rem;
    overflow: hidden;
    flex-shrink: 0;
}
.vf-os-icon img {
    max-width: 100%;
    max-height: 100%;
    width: 24px;
    height: 24px;
    object-fit: contain;
}
.vf-os-label {
    font-weight: 600;
    font-size: 12px;
    line-height: 1.2;
}
.vf-os-version {
    font-size: 10px;
    color: #888;
    line-height: 1.2;
}
.vf-os-eol-badge {
    display: inline-block;
    background: #dc3545;
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 3px;
    margin-top: 3px;
}
#vf-os-details {
    border-top: 1px solid #dee2e6;
    padding-top: 10px;
}
.vf-os-search {
    margin-bottom: 10px;
}

@media (max-width: 768px) {
    .vf-os-grid {
        gap: 6px;
    }
    .vf-os-card {
        width: calc(50% - 3px);
        min-width: 100px;
    }
}

/* ---------------- Control Panel card ----------------
   Not a pane: this sits between the hero and the tab strip and never hides.
   Someone who ordered cPanel bought cPanel — the VPS is how it gets
   delivered — so the panel address is the headline, and the accent rail and
   the full-size Open button are there to make it read that way before
   anything else on the page. */
.vf-panel-card {
    border-left: 4px solid #337ab7;
    padding: 16px 18px;
}
.vf-panel-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.vf-panel-eyebrow {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: #6c757d;
}
.vf-panel-app {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.1;
}
/* Button first on narrow screens, beside the facts on wide ones — the action
   should never be below the fold on a phone. */
.vf-panel-main {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
@media (min-width: 720px) {
    .vf-panel-main {
        flex-direction: row-reverse;
        align-items: flex-start;
        justify-content: space-between;
        gap: 24px;
    }
}
/* This is an <a> that has to look like a button, which puts it in the path of
   every link rule the surrounding theme defines. A bare `.vf-panel-open`
   (0,1,0) loses to a theme's `.card a` (0,1,1), and loses to `a:visited` for
   any customer who has opened their panel before — which is why the label
   rendered dark on blue instead of white.

   Hence `.vf-panel-card a.vf-panel-open` (0,2,1) and an explicit state for
   :link/:visited/:hover/:focus/:active. Specificity rather than !important,
   so an operator restyling this still can. */
.vf-panel-card a.vf-panel-open,
.vf-panel-card a.vf-panel-open:link,
.vf-panel-card a.vf-panel-open:visited {
    display: inline-block;
    align-self: flex-start;
    background: #337ab7;
    color: #fff;
    font-weight: 600;
    font-size: 0.95rem;
    text-decoration: none;
    padding: 10px 20px;
    border-radius: 6px;
    white-space: nowrap;
    border: 0;
    transition: background 0.15s;
}
.vf-panel-card a.vf-panel-open:hover,
.vf-panel-card a.vf-panel-open:focus,
.vf-panel-card a.vf-panel-open:active {
    background: #2a6496;
    color: #fff;
    text-decoration: none;
}
.vf-panel-facts {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
.vf-panel-fact {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}
.vf-panel-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: #6c757d;
}
.vf-panel-value {
    font-size: 14px;
    word-break: break-all;
}
/* Same trap, smaller stakes: a theme's a:visited would repaint the address a
   different colour once the customer has opened it. */
.vf-panel-card a.vf-panel-url,
.vf-panel-card a.vf-panel-url:link,
.vf-panel-card a.vf-panel-url:visited {
    color: #337ab7;
}
.vf-panel-card a.vf-panel-url:hover,
.vf-panel-card a.vf-panel-url:focus {
    color: #2a6496;
}
.vf-panel-password {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
/* Masked and revealed share one element so the row does not resize when the
   password appears — a layout jump under the cursor is how you get a misclick
   on whatever lands where the button used to be. */
#vf-panel-secret {
    font-family: SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    word-break: break-all;
}
.vf-panel-installing {
    border: 1px dashed #dee2e6;
    border-radius: 6px;
    padding: 14px 16px;
}
.vf-panel-installing-title {
    display: flex;
    align-items: center;
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 6px;
}
.vf-panel-notice,
.vf-panel-foot {
    margin-top: 14px;
    margin-bottom: 0;
}
.vf-panel-notes {
    margin-top: 14px;
}
.vf-panel-notes ul {
    margin: 4px 0 0;
    padding-left: 20px;
    font-size: 13px;
}

/* ---------------- SSH key chooser ----------------
   Shared by the order form (injected in hooks.php) and the Rebuild tab.
   Progressive disclosure: only the body of the selected mode is rendered,
   and the default mode ("password only") has no body at all, so a customer
   who does not know what an SSH key is is never shown an open field. */
.vf-ssh {
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 12px;
}
.vf-ssh[hidden] {
    display: none;
}
.vf-ssh-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}
.vf-ssh-title {
    font-weight: 600;
    font-size: 0.95rem;
}
.vf-ssh-badge {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #6c757d;
    background: rgba(0,0,0,0.06);
    border-radius: 10px;
    padding: 2px 7px;
}
.vf-ssh-hint {
    font-size: 12px;
    color: #6c757d;
    line-height: 1.45;
    margin: 0 0 10px;
}
.vf-ssh-choices {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.vf-ssh-choice {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 0;
    padding: 9px 11px;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    cursor: pointer;
    font-weight: 400;
    transition: border-color 0.15s, background-color 0.15s;
}
.vf-ssh-choice[hidden] {
    display: none;
}
.vf-ssh-choice:hover {
    border-color: #adb5bd;
    background: rgba(0,0,0,0.02);
}
.vf-ssh-choice input {
    margin: 3px 0 0;
    flex-shrink: 0;
}
.vf-ssh-choice-selected {
    border-color: #337ab7;
    background: rgba(51,122,183,0.06);
    box-shadow: inset 0 0 0 1px rgba(51,122,183,0.25);
}
.vf-ssh-choice-text {
    display: block;
    line-height: 1.3;
}
.vf-ssh-choice-label {
    display: block;
    font-size: 13px;
    font-weight: 600;
}
.vf-ssh-choice-desc {
    display: block;
    font-size: 11.5px;
    color: #6c757d;
    margin-top: 2px;
}
.vf-ssh-body {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed #dee2e6;
}
.vf-ssh-body[hidden] {
    display: none;
}
.vf-ssh-body > label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    margin-bottom: 4px;
}
.vf-ssh-body textarea {
    font-family: SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
}
.vf-ssh-error {
    color: #dc3545;
    font-size: 12px;
    margin-top: 8px;
}
.vf-ssh-error[hidden] {
    display: none;
}
.vf-ssh-privkey {
    margin-top: 12px;
    border: 2px solid #dc3545;
    border-radius: 6px;
    padding: 12px;
}
.vf-ssh-privkey[hidden] {
    display: none;
}
.vf-ssh-privkey-warning {
    color: #dc3545;
    font-weight: 700;
    font-size: 13px;
    margin-bottom: 8px;
}
.vf-ssh-privkey textarea {
    margin-bottom: 8px;
}
.vf-ssh-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}
.vf-ssh-ok {
    color: #28a745;
    font-weight: 700;
    font-size: 12px;
}

/* Resource panel */
.vf-resource-item .progress {
    background-color: rgba(0,0,0,0.08);
    border-radius: 4px;
}

/* Order form slider UI */
.vf-slider-container {
    padding: 8px 0;
}
.vf-slider-value {
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 4px;
    text-align: center;
}
.vf-slider {
    width: 100%;
    height: 6px;
    -webkit-appearance: none;
    appearance: none;
    background: #ddd;
    border-radius: 3px;
    outline: none;
    cursor: pointer;
}
.vf-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #337ab7;
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.vf-slider::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #337ab7;
    cursor: pointer;
    border: 2px solid #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}

/* Toggle Switch */
.vf-toggle-input {
    display: none;
}
.vf-toggle-switch {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    background: #ccc;
    border-radius: 10px;
    transition: background 0.2s;
    flex-shrink: 0;
}
.vf-toggle-switch::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.2s;
}
.vf-toggle-input:checked + .vf-toggle-switch {
    background: #28a745;
}
.vf-toggle-input:checked + .vf-toggle-switch::after {
    transform: translateX(16px);
}

/* Responsive adjustments */
@media (max-width: 768px) {
    /* Was a full-width column: four stacked bars, ~180px of vertical space
       for controls most visits never touch. Now the compact buttons share
       the width two-up and the row stays two lines at worst. */
    .vf-power-buttons .vf-btn-power {
        flex: 1 1 calc(50% - 3px);
    }
    .vf-ip-row {
        flex-wrap: wrap;
    }
}

/* =========================================================================
   Reverse DNS panel
   ========================================================================= */
.vf-rdns-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid rgba(0,0,0,.06);
}
.vf-rdns-row:last-child { border-bottom: none; }
.vf-rdns-ip {
    font-family: monospace;
    font-size: 13px;
    min-width: 180px;
    font-weight: 600;
}
.vf-rdns-edit {
    display: flex;
    flex: 1 1 auto;
    gap: 6px;
    align-items: center;
    min-width: 240px;
}
.vf-rdns-input {
    flex: 1 1 auto;
    min-width: 180px;
    max-width: 420px;
    font-family: monospace;
    font-size: 13px;
}
.vf-rdns-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    line-height: 1.4;
    white-space: nowrap;
}
.vf-rdns-msg {
    flex-basis: 100%;
    font-size: 12px;
    display: none;
    padding-left: 180px;
}
.vf-rdns-admin-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
    font-size: 13px;
}
.vf-rdns-ip-admin {
    font-family: monospace;
    font-weight: 600;
    min-width: 180px;
}
.vf-rdns-ptr-admin {
    font-family: monospace;
    color: #333;
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}
@media (max-width: 768px) {
    .vf-rdns-row { flex-direction: column; align-items: stretch; }
    .vf-rdns-edit { flex-direction: column; align-items: stretch; }
    .vf-rdns-msg { padding-left: 0; }
}

/* Subnet-only rows (IPv6 /64 allocations). Distinct visual treatment so
   customers see "this is a subnet, not a host" without reading the badge. */
.vf-rdns-subnet-row {
    background: rgba(23, 162, 184, 0.04);
    border-left: 3px solid #17a2b8;
    padding-left: 8px;
}
.vf-rdns-subnet-form {
    flex-basis: 100%;
    padding: 10px 0 0 180px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.vf-rdns-subnet-inputs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}
.vf-rdns-subnet-actions {
    display: flex;
    gap: 6px;
    align-items: center;
}
@media (max-width: 768px) {
    .vf-rdns-subnet-form { padding-left: 0; }
    .vf-rdns-subnet-inputs { flex-direction: column; }
}

/* ---------------- In-page Section Nav ---------------- */
.vf-section-nav-body {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.vf-section-nav-body::before {
    content: "Jump to:";
    font-weight: 600;
    color: #555;
    margin-right: 4px;
    font-size: 13px;
}
.vf-nav-link {
    display: inline-block;
    padding: 4px 10px;
    border: 1px solid #d6d8db;
    border-radius: 4px;
    background: #f8f9fa;
    color: #333;
    text-decoration: none;
    font-size: 13px;
    line-height: 1.4;
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.vf-nav-link:hover,
.vf-nav-link:focus {
    background: #e9ecef;
    border-color: #adb5bd;
    color: #000;
    text-decoration: none;
    outline: none;
}
@media (max-width: 576px) {
    .vf-section-nav-body::before { display: block; width: 100%; margin-bottom: 4px; }
}

/* ---------------- Server Overview meta bar ---------------- */
.vf-overview-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    padding: 8px 12px;
    background: #f8f9fa;
    border: 1px solid #e6e8eb;
    border-radius: 4px;
}
.vf-meta-chip {
    display: inline-block;
    padding: 3px 10px;
    background: #fff;
    border: 1px solid #d6d8db;
    border-radius: 12px;
    font-size: 12px;
    color: #333;
    line-height: 1.5;
}
.vf-meta-chip-muted {
    color: #6c757d;
    font-style: italic;
    background: transparent;
    border: none;
    padding: 3px 4px;
}
.vf-mask-ips-btn {
    margin-left: auto;
    font-size: 12px;
    padding: 3px 10px;
}
@media (max-width: 576px) {
    .vf-mask-ips-btn { margin-left: 0; width: 100%; }
}

/* ---------------- Resource meters ----------------
   One card per resource, each showing use against allocation. Replaces three
   separate blocks that between them printed "Memória" three times on one
   screen without ever putting used next to total.

   auto-fit + minmax means the row reflows from four across to two to one
   without a media query per breakpoint. */
.vf-meter-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 18px 24px;
}
.vf-meter {
    min-width: 0;
}
.vf-meter-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 7px;
}
.vf-meter-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #6c757d;
}
/* Tabular figures so the numbers do not jitter sideways as they tick — this
   value updates every 30 seconds. */
.vf-meter-value {
    font-size: 1.05rem;
    font-weight: 600;
    color: #1b2733;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.vf-meter-sub {
    margin-top: 6px;
    font-size: 12px;
    color: #6c757d;
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    min-height: 18px;
}
.vf-meter-alloc::before {
    content: "/";
    margin-right: 6px;
    color: #adb5bd;
}
/* Meters with no bar (storage) keep the same height as the ones with, so the
   row of cards stays on one baseline. */
#vf-meter-storage .vf-meter-sub {
    margin-top: 14px;
}

/* ---------------- Disk I/O strip ---------------- */
.vf-diskio {
    display: flex;
    align-items: baseline;
    gap: 18px;
    flex-wrap: wrap;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid #eef1f4;
    font-size: 13px;
}
.vf-diskio-pair {
    display: inline-flex;
    gap: 6px;
    font-variant-numeric: tabular-nums;
}
.vf-diskio-since {
    font-size: 11.5px;
    margin-left: auto;
}

/* ---------------- Meter bars ---------------- */
.vf-live-bar {
    width: 100%;
    height: 8px;
    background: #eef1f4;
    border-radius: 4px;
    overflow: hidden;
    position: relative;
}
/* min-width so a real-but-tiny value still shows. At 0.1% the old bar was
   sub-pixel and read as "broken" rather than "idle". */
.vf-live-bar-fill {
    height: 100%;
    min-width: 3px;
    border-radius: 4px;
    background: linear-gradient(90deg, #28a745, #20c997);
    transition: width 0.5s ease, background 0.3s ease;
}
.vf-live-bar-fill.bg-warning {
    background: linear-gradient(90deg, #ffc107, #fd7e14);
}
.vf-live-bar-fill.bg-danger {
    background: linear-gradient(90deg, #dc3545, #c82333);
}
.vf-livestats-updated {
    color: #6c757d;
}

/* ---------------- Filesystem rows ---------------- */
.vf-fs-row .progress {
    background-color: #e9ecef;
}
.vf-fs-row .progress-bar {
    background-color: #337ab7;
    transition: width 0.5s ease;
}
.vf-fs-row .progress-bar.bg-warning { background-color: #ffc107 !important; }
.vf-fs-row .progress-bar.bg-danger  { background-color: #dc3545 !important; }

/* ---------------- Layout: side-by-side panel grid ---------------- */
/*
 * Used to lay out compact panels (Traffic + Live Stats) side-by-side on
 * wide screens. CSS Grid with auto-fit handles the case where one panel is
 * display:none (e.g. Live Stats hidden when remoteState is unavailable) —
 * the visible panel fills the row.
 */
.vf-panel-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
    gap: 1rem;
}
.vf-panel-grid > .panel,
.vf-panel-grid > .card {
    margin-bottom: 0 !important;
    height: 100%;
}

/* ---------------- Server Overview rename row ---------------- */
/*
 * Was previously a single flex row that squished the Save button on
 * narrower viewports. Wrap-on-overflow + min-widths keep buttons readable
 * regardless of cell width.
 */
.vf-rename-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.vf-rename-input-field {
    flex: 1 1 160px;
    min-width: 140px;
    max-width: 240px;
}
.vf-rename-btn-randomise,
.vf-rename-btn-save {
    flex: 0 0 auto;
    white-space: nowrap;
    min-width: 38px;
}
.vf-rename-btn-save {
    min-width: 56px;
}

/* ---------------- IP cell rows (Server Overview) ---------------- */
/*
 * Each IPv4/IPv6 address renders as a compact row: address span + copy
 * button. Replaces the standalone Network panel; the per-address copy
 * affordance moved here.
 */
.vf-ip-cell-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 2px;
    line-height: 1.5;
}
.vf-ip-cell-row .vf-ip-address {
    word-break: break-all;
}
.vf-ip-cell-row:last-child {
    margin-bottom: 0;
}

/* ---------------- Sensitive-input masking ---------------- */
/*
 * Companion to the JS-based IP text masking. When body.vf-mask-active is
 * set, render the value of any input.vf-sensitive as discs so the actual
 * characters don't leak into a screenshot. Hover/focus restores the real
 * value for editing — the customer can still see what they're typing.
 *
 * `text-security` is widely supported under the -webkit- prefix (Chrome,
 * Edge, Safari) and as the unprefixed property in modern Firefox. Falls
 * through to `-webkit-text-security: disc` everywhere else; if a browser
 * truly doesn't honour it the screenshot mask just isn't applied to the
 * input field — the IP cells still mask, so the customer's worst case is
 * an unmasked rDNS hostname (failsafe-soft, not security-critical).
 */
body.vf-mask-active input.vf-sensitive {
    -webkit-text-security: disc;
    text-security: disc;
    font-family: text-security-disc, sans-serif;
    transition: filter 0.15s ease;
}
body.vf-mask-active input.vf-sensitive:focus,
body.vf-mask-active input.vf-sensitive:hover {
    -webkit-text-security: none;
    text-security: none;
    font-family: inherit;
}

/* =========================================================================
   vfConfirm — in-page confirmation modal
   ========================================================================= */
.vf-confirm-backdrop{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:rgba(15,23,42,0);backdrop-filter:blur(0px);transition:background 0.2s ease,backdrop-filter 0.2s ease}
.vf-confirm-backdrop.vf-confirm-visible{background:rgba(15,23,42,0.45);backdrop-filter:blur(4px)}
.vf-confirm-dialog{background:#ffffff;border-radius:18px;box-shadow:0 24px 60px rgba(15,23,42,0.18),0 4px 12px rgba(15,23,42,0.08);padding:28px 28px 24px;max-width:420px;width:calc(100% - 32px);display:flex;flex-direction:column;gap:16px;transform:translateY(12px) scale(0.97);opacity:0;transition:transform 0.22s cubic-bezier(0.34,1.56,0.64,1),opacity 0.18s ease}
.vf-confirm-backdrop.vf-confirm-visible .vf-confirm-dialog{transform:translateY(0) scale(1);opacity:1}
.vf-confirm-icon{width:44px;height:44px;border-radius:12px;background:#f1f5f9;display:flex;align-items:center;justify-content:center;color:#64748b;flex-shrink:0}
.vf-confirm-icon.vf-confirm-icon-danger{background:#fff1f2;color:#e11d48}
.vf-confirm-body{display:flex;flex-direction:column;gap:6px}
.vf-confirm-title{font-size:16px;font-weight:700;color:#0f172a;line-height:1.3}
.vf-confirm-msg{font-size:13.5px;color:#475569;line-height:1.6}
.vf-confirm-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:4px}
.vf-confirm-btn{appearance:none;border-radius:999px;padding:9px 20px;font-size:13.5px;font-weight:600;cursor:pointer;border:none;transition:all 0.15s ease;line-height:1}
.vf-confirm-btn-cancel{background:#f1f5f9;color:#475569;border:1.5px solid #e2e8f0}
.vf-confirm-btn-cancel:hover{background:#e2e8f0;color:#0f172a}
.vf-confirm-btn-danger{background:#e11d48;color:#ffffff;box-shadow:0 2px 8px rgba(225,29,72,0.30)}
.vf-confirm-btn-danger:hover{background:#be123c;box-shadow:0 4px 14px rgba(225,29,72,0.35)}
.vf-confirm-btn-danger:active{transform:translateY(1px)}
.vf-confirm-btn-primary{background:#2563eb;color:#ffffff;box-shadow:0 2px 8px rgba(37,99,235,0.28)}
.vf-confirm-btn-primary:hover{background:#1d4ed8}

/* =========================================================================
   HERO — always-visible summary card (HosTMF fork)
   =========================================================================
   Replaces the old "VNC Console" panel + "Server Overview" header. Holds the
   identity (state dot, name, badge), the meta chips, and every action a
   customer reaches for on a typical visit. Sits above the tab strip and never
   changes as tabs switch, so the primary controls stay put.

   Colours are hardcoded rather than inherited from the theme because WHMCS
   themes disagree wildly on what .card/.panel means; the module has always
   painted its own surfaces (see .vf-confirm-* above) for exactly this reason.
   ========================================================================= */
.vf-hero {
    background: #fff;
    border: 1px solid #e6e8eb;
    border-radius: 8px;
    padding: 18px 20px;
}
/* A COLUMN, not a wrapping row.
   It used to be `flex-wrap: wrap` with identity and actions as siblings, and
   that is what made the action row move: a narrow set of buttons fitted
   beside the title (squeezing the identity block to its 320px basis, which
   pushed the meta chips onto two extra lines), while a wide set wrapped
   underneath (giving identity the full width, so the chips fitted on one).
   The card was two different shapes depending on whether the server happened
   to be running.

   Stacking is deterministic: title, then chips, then actions, always in that
   order and always in the same place. */
.vf-hero-top {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.vf-hero-identity {
    /* No flex-basis: in a column container that would set the HEIGHT. */
    min-width: 0;
}
.vf-hero-title-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.vf-hero-name {
    font-size: 1.25rem;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.3;
    word-break: break-word;
}

/* State dot — a glanceable running/stopped signal that reads before the badge
   text does. Pulses only while up, so a stopped server is visually quiet. */
.vf-state-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #cbd5e1;
    flex-shrink: 0;
    display: inline-block;
}
.vf-state-dot-up {
    background: #22c55e;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.18);
}
.vf-state-dot-down {
    background: #ef4444;
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18);
}
.vf-state-dot-warn {
    background: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18);
}

/* Meta chip row. Unlike the old .vf-overview-meta this has no card background
   of its own — the hero already provides one, and nesting two panels looked
   like a rendering bug. */
.vf-hero-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.vf-meta-chip-mono {
    font-family: SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
    font-size: 11.5px;
}
.vf-hero-meta .vf-mask-ips-btn {
    margin-left: 0;
}

.vf-hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    /* Holds the row's height while buttons come and go with the server's
       state, so the feedback area below it does not slide up and down. */
    min-height: 36px;
    /* Hairline separating "what this server is" from "what you can do to
       it" — the card reads as two zones instead of one long pile. */
    padding-top: 13px;
    border-top: 1px solid #eef1f4;
}
.vf-hero-actions-divider {
    width: 1px;
    align-self: stretch;
    min-height: 28px;
    background: #e6e8eb;
}
.vf-hero-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.vf-hero-link-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 36px;
    padding: 0 15px;
    border-radius: 8px;
    border: 1px solid transparent;
    font-weight: 600;
    font-size: 0.85rem;
    white-space: nowrap;
    box-shadow: none;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.vf-hero-link-solid,
.vf-hero-link-solid:link,
.vf-hero-link-solid:visited {
    background: #337ab7;
    border-color: #337ab7;
    color: #fff;
}
.vf-hero-link-solid:hover:not(:disabled),
.vf-hero-link-solid:focus:not(:disabled) {
    background: #2a6496;
    border-color: #2a6496;
    color: #fff;
}
/* "Painel Cloud" had no chrome at all — just an icon and a word floating
   beside two solid buttons. An outline gives it the same footprint without
   competing with the primary actions. */
.vf-hero-link-ghost {
    background: #fff;
    border-color: #dbe1e8;
    color: #33414f;
}
.vf-hero-link-ghost:hover:not(:disabled),
.vf-hero-link-ghost:focus:not(:disabled) {
    background: #f4f7fa;
    border-color: #c3ccd6;
    color: #16202b;
}
.vf-hero-link-btn:disabled { opacity: 0.55; cursor: default; }
.vf-hero-feedback > * {
    margin-top: 12px;
    margin-bottom: 0;
}
.vf-hero-feedback:empty {
    display: none;
}

/* =========================================================================
   TABS
   =========================================================================
   Hand-rolled rather than Bootstrap's .nav-tabs because the module must render
   identically under BS3, BS4 and BS5 — their tab markup and active-state
   classes are mutually incompatible. Panes are toggled by .vf-pane-active
   (see vfActivateTab in module.js), never by inline display, so jQuery .show()
   calls inside a pane can't fight the tab controller.
   ========================================================================= */
.vf-tabs {
    background: #fff;
    border: 1px solid #e6e8eb;
    border-radius: 8px;
    overflow: hidden;
}
.vf-tabstrip {
    display: flex;
    gap: 2px;
    padding: 0 8px;
    border-bottom: 1px solid #e6e8eb;
    background: #f8f9fa;
    overflow-x: auto;
    /* Horizontal scroll on narrow screens beats wrapping into a second row —
       a wrapped strip keeps changing height as tabs come and go. */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.vf-tabstrip::-webkit-scrollbar {
    display: none;
}
.vf-tab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 12px 16px;
    font-size: 0.9rem;
    font-weight: 600;
    color: #64748b;
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.vf-tab:hover {
    color: #0f172a;
}
.vf-tab:focus-visible {
    outline: 2px solid #2563eb;
    outline-offset: -2px;
}
.vf-tab-active {
    color: #2563eb;
    border-bottom-color: #2563eb;
}
.vf-pane {
    display: none;
    padding: 20px;
}
.vf-pane-active {
    display: block;
}

/* Subsections group related controls inside a pane without stacking another
   card border. A leading rule separates each from the one above it; the first
   in a pane opts out via .vf-subsection-first. */
.vf-subsection {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid #eef0f2;
}
.vf-subsection-first,
.vf-pane > .vf-subsection:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}
.vf-subsection-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}
.vf-subsection-title {
    font-size: 0.95rem;
    font-weight: 700;
    color: #0f172a;
    margin: 0;
}

/* =========================================================================
   DETAIL GRID — label/value pairs (Overview + Billing panes)
   =========================================================================
   Replaces the old Bootstrap .row/.col-xs-4 markup. A two-column grid with a
   fixed label track keeps every value left-aligned regardless of label length,
   which the float-based version never managed across themes.
   ========================================================================= */
.vf-detail-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* align-items:start stops the taller column (the rename row has an input
       and two buttons) from stretching its sibling's rows out of line — the
       two columns used to drift apart by a few pixels per row. */
    align-items: start;
    gap: 2px 32px;
}
.vf-detail-col {
    min-width: 0;
}
.vf-detail-row {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
    padding: 6px 0;
}
.vf-detail-label {
    font-weight: 700;
    color: #475569;
    font-size: 0.85rem;
    padding-top: 2px;
}
.vf-detail-value {
    min-width: 0;
    word-break: break-word;
}

@media (max-width: 768px) {
    /* .vf-hero-top is a column at every width now, so the old override here
       is gone rather than repeated. */
    .vf-hero-actions-divider {
        display: none;
    }
    .vf-detail-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }
    .vf-pane {
        padding: 16px;
    }
    .vf-tab {
        padding: 12px;
        font-size: 0.85rem;
    }
}

@media (max-width: 576px) {
    .vf-detail-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 2px;
    }
    .vf-hero-links,
    .vf-hero-actions,
    .vf-hero-actions .vf-power-buttons {
        width: 100%;
    }
    .vf-hero-link-btn {
        flex: 1 1 auto;
        justify-content: center;
    }
}

/* =========================================================================
   Revealed credential block (server password reset)

   Shown once, never stored. Styled as its own thing rather than reusing
   .vf-panel-fact because it lives inside a Bootstrap .alert, whose colours
   the themes disagree about — the values here are explicit for that reason.
   ========================================================================= */
/* Hidden by the inline style in overview.tpl, not from here: two sources of
   display for one element is how a .show() ends up fighting a stylesheet. */
.vf-cred-result {
    margin-top: 12px;
}
.vf-cred-once {
    font-weight: 700;
    margin-bottom: 10px;
}
.vf-cred-row {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}
.vf-cred-row + .vf-cred-row {
    margin-top: 8px;
}
.vf-cred-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    opacity: 0.75;
}
.vf-cred-value {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 14px;
    min-width: 0;
}
/* A generated password has no spaces to wrap at, so it must be allowed to
   break mid-token or it will push the alert wider than the pane. */
.vf-cred-value code {
    background: rgba(0, 0, 0, 0.06);
    border-radius: 4px;
    padding: 3px 8px;
    font-size: 14px;
    color: inherit;
    word-break: break-all;
    overflow-wrap: anywhere;
}
