/* Vikalink Client Portal — Dashboard Shell
   Palette matches the Vikalink Admin Dashboard (billing): clean white/
   light-gray surfaces throughout, including the sidebar — no dark or
   navy chrome anywhere in the light theme. Blue primary with a teal
   accent for highlights. --primary-dark is kept around as a color
   token (a few gradients/emphasis-text spots still use it) but nothing
   uses it as a large surface fill anymore; see the dark-hero-turned-
   light-card comments further down this file (.announce-ticker,
   .custom-build-cta, .promo-hero-banner, .domain-search-panel,
   .status-server-stat) for the pieces that used to.
   #F5F7FA bg | #FFFFFF surface/sidebar | #1D4ED8 primary | #0EA5A5 accent | #5D6A85 muted | #151B2B ink
*/

:root {
    --bg: #F5F7FA;
    --surface: #FFFFFF;
    --surface-raised: #F5F8FC;
    --line: #DEE4EF;
    --ink: #0A0A0D;
    --muted: #5D6A85;
    --primary: #1D4ED8;
    --primary-dark: #0B1B3B;
    --primary-tint: #E7EEFE;
    --accent: #0EA5A5;
    --accent-tint: #E1F6F6;
    --danger: #C0392B;
    --danger-tint: #FBEAE7;
    --success: #1E8E5A;
    --success-tint: #E4F5EC;
    --warning: #B7791F;
    --warning-tint: #FBF0DE;
    --info: #3A6EA5;
    --info-tint: #E6EDF6;
    --radius: 10px;
    --shadow: 0 1px 2px rgba(11, 27, 59, .06), 0 8px 24px -12px rgba(11, 27, 59, .14);
    --shadow-elevated: 0 1px 1px rgba(11, 27, 59, .04), 0 6px 12px -4px rgba(11, 27, 59, .1), 0 24px 48px -16px rgba(11, 27, 59, .18), 0 2px 0 rgba(255, 255, 255, .6) inset;
    --shadow-tile: 0 1px 2px rgba(11, 27, 59, .05), 0 3px 6px -2px rgba(11, 27, 59, .08);
    --shadow-tile-hover: 0 2px 4px rgba(11, 27, 59, .07), 0 12px 20px -6px rgba(11, 27, 59, .18);
    --primary-shade: #1640B0;
    /* Sidebar used to be a dark-navy panel with light-on-dark tokens
       (see the dark-theme override below, where that's still true).
       In the light theme it's now just another white surface, so
       these are plain dark-ink-on-white tokens instead — kept as
       their own --sidebar-* set (rather than reusing --ink/--muted/
       --line directly) because a couple of other one-off "hero" panels
       elsewhere in this file (.promo-hero-banner, .domain-search-panel)
       intentionally reuse them too, and having a dedicated set means
       those keep matching the sidebar automatically if either changes. */
    --sidebar-bg: #FFFFFF;
    --sidebar-text: #0A0A0D;
    --sidebar-muted: #5D6A85;
    --sidebar-muted-dim: #8B96AF;
    --sidebar-border: #E7ECF4;
    --sidebar-hover: #EEF3FC;
    --sidebar-width: 248px;
    --header-height: 64px;
    --font-display: 'Sora', 'Segoe UI', sans-serif;
    --font-body: 'Inter', 'Segoe UI', sans-serif;
    --font-mono: 'IBM Plex Mono', 'Courier New', monospace;
}

/* Dark theme — toggled via [data-theme="dark"] on <html> (see the
   inline anti-flash script in each page's <head> and the toggle button
   wired up in partials/footer.php). Same token names as :root above,
   just re-pointed, so every rule elsewhere in this file that already
   uses var(--bg)/var(--surface)/etc. picks this up automatically with
   no further edits needed.
   Deliberately kept to soft mid slate tones rather than near-black —
   #0B1220/#060B18 (the old --bg/--primary-dark here) read as heavy as
   the light theme's navy sidebar did, so both got the same "no dark
   shades" pass: everything below sits in a #1B2333-#3A445E slate
   range rather than dropping toward black, and shadows are toned down
   to match (a shadow this soft-charcoal-on-slate doesn't need the same
   opacity a true near-black background did to read as elevated). */
html[data-theme="dark"] {
    --bg: #1B2333;
    --surface: #232C40;
    --surface-raised: #2A3449;
    --line: #3A445E;
    --ink: #EDF1F9;
    --muted: #A7B2CC;
    --primary: #5C8AFF;
    --primary-dark: #29334A;
    --primary-tint: #263255;
    --accent: #29C7C1;
    --accent-tint: #223C46;
    --danger: #F0685A;
    --danger-tint: #402A2C;
    --success: #3FCE8A;
    --success-tint: #1E3A2C;
    --warning: #E3AC4E;
    --warning-tint: #40331C;
    --info: #74A5DD;
    --info-tint: #253347;
    --shadow: 0 1px 2px rgba(0, 0, 0, .18), 0 8px 24px -12px rgba(0, 0, 0, .3);
    --shadow-elevated: 0 1px 1px rgba(0, 0, 0, .18), 0 6px 14px -4px rgba(0, 0, 0, .24), 0 28px 56px -16px rgba(0, 0, 0, .4), 0 1px 0 rgba(255, 255, 255, .04) inset;
    --shadow-tile: 0 1px 2px rgba(0, 0, 0, .15), 0 3px 6px -2px rgba(0, 0, 0, .18);
    --shadow-tile-hover: 0 2px 6px rgba(0, 0, 0, .18), 0 14px 24px -6px rgba(0, 0, 0, .3);
    --primary-shade: #7AA0FF;
    --sidebar-bg: #232C40;
    --sidebar-text: #EDF1F9;
    --sidebar-muted: #A7B2CC;
    --sidebar-muted-dim: #7C87A2;
    --sidebar-border: #3A445E;
    --sidebar-hover: #2A3449;
}

* {
    box-sizing: border-box;
}

html, body {
    height: 100%;
    margin: 0;
    overflow-x: hidden;
    /* Belt-and-braces alongside the maximum-scale/user-scalable=no
       viewport meta tag on every page: stops touch-drag from panning
       the page horizontally (or being caught mid-pan by a stray pinch)
       on iOS Safari, which is what free left/right drift on mobile
       usually turns out to be — not a layout bug, a zoom/pan one. */
    touch-action: pan-y;
    overscroll-behavior-x: none;
}

body {
    font-family: var(--font-body);
    background: var(--bg);
    color: var(--ink);
    transition: background-color .15s ease, color .15s ease;
}

/* Theme toggle button — lives in the topbar (partials/header.php),
   next to the user cluster. */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: linear-gradient(150deg, var(--primary-tint), var(--surface) 65%);
    color: var(--primary);
    cursor: pointer;
    flex-shrink: 0;
    box-shadow: var(--shadow-tile), inset 0 0 0 1px var(--line);
    transition: box-shadow .16s ease, background .16s ease, color .16s ease, transform .16s ease;
}

.theme-toggle:hover {
    color: var(--primary);
    box-shadow: var(--shadow-tile-hover), inset 0 0 0 1px var(--primary);
    transform: translateY(-2px);
}

.theme-toggle svg {
    width: 18px;
    height: 18px;
}

.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }

html[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
html[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* Notification bell — lives in the topbar (partials/header.php),
   between the theme toggle and the user cluster. */
.notif-wrap {
    position: relative;
    flex-shrink: 0;
}

.notif-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: linear-gradient(150deg, var(--primary-tint), var(--surface) 65%);
    color: var(--primary);
    cursor: pointer;
    position: relative;
    box-shadow: var(--shadow-tile), inset 0 0 0 1px var(--line);
    transition: box-shadow .16s ease, background .16s ease, color .16s ease, transform .16s ease;
}

.notif-toggle:hover {
    box-shadow: var(--shadow-tile-hover), inset 0 0 0 1px var(--primary);
    transform: translateY(-2px);
}

.notif-toggle[aria-expanded="true"] {
    background: var(--primary);
    color: #fff;
    box-shadow: var(--shadow-tile-hover);
}

.notif-toggle svg {
    width: 18px;
    height: 18px;
}

.notif-toggle .icon-bell-active { display: none; }

.notif-toggle[aria-expanded="true"] .icon-bell { display: none; }
.notif-toggle[aria-expanded="true"] .icon-bell-active { display: block; }

/* Cart — topbar icon (was a sidebar Store > Cart link), same size/
   shape/hover language as .notif-toggle so the two sit as a matched
   pair, just a plain link instead of a toggle+panel (cart.php is a
   full page, not a dropdown). */
.cart-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 999px;
    border: 1px solid transparent;
    background: linear-gradient(150deg, var(--primary-tint), var(--surface) 65%);
    color: var(--primary);
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    box-shadow: var(--shadow-tile), inset 0 0 0 1px var(--line);
    transition: box-shadow .16s ease, background .16s ease, color .16s ease, transform .16s ease;
    text-decoration: none;
}
.cart-toggle:hover {
    box-shadow: var(--shadow-tile-hover), inset 0 0 0 1px var(--primary);
    transform: translateY(-2px);
}
.cart-toggle svg { width: 18px; height: 18px; }

.notif-badge {
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    line-height: 17px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--surface);
}

.notif-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: 340px;
    max-width: calc(100vw - 32px);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: var(--shadow-elevated);
    z-index: 30;
    overflow: hidden;
    animation: notifPanelIn .16s ease;
}

@keyframes notifPanelIn {
    from { opacity: 0; transform: translateY(-6px) scale(.97); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.notif-panel-head {
    padding: 14px 16px 10px;
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 700;
    border-bottom: 1px solid var(--line);
}

.notif-empty {
    padding: 26px 16px;
    text-align: center;
    font-size: 13px;
    color: var(--muted);
}

.notif-list {
    max-height: 360px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.notif-item {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    padding: 12px 16px;
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid var(--line);
    transition: background-color .12s ease;
}

.notif-item:last-child {
    border-bottom: none;
}

.notif-item:hover {
    background: var(--surface-raised);
}

.notif-item-icon {
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-tint);
    color: var(--primary);
}

.notif-item-icon svg {
    width: 15px;
    height: 15px;
}

.notif-item-ticket .notif-item-icon {
    background: var(--info-tint);
    color: var(--info);
}

.notif-item-announcement .notif-item-icon {
    background: var(--warning-tint);
    color: var(--warning);
}

.notif-item-server .notif-item-icon {
    background: var(--info-tint);
    color: var(--info);
}

/* Server notifications recolour by severity — offline/degraded read
   as alerts, a status flipping back to online reads as good news —
   same danger/warning/success split server-status.php's own pill and
   banner use, so the bell agrees with the Server Status page. */
.notif-item-severity-danger .notif-item-icon {
    background: var(--danger-tint);
    color: var(--danger);
}

.notif-item-severity-warning .notif-item-icon {
    background: var(--warning-tint);
    color: var(--warning);
}

.notif-item-severity-success .notif-item-icon {
    background: var(--success-tint);
    color: var(--success);
}

.notif-item-body {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.notif-item-title {
    font-size: 13px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notif-item-meta {
    font-size: 11.5px;
    color: var(--muted);
}

.notif-panel-foot {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 10px 16px;
    border-top: 1px solid var(--line);
    background: var(--surface-raised);
}

.notif-panel-foot a {
    font-size: 12px;
    font-weight: 600;
    color: var(--primary);
    text-decoration: none;
}

.notif-panel-foot a:hover {
    text-decoration: underline;
}

@media (max-width: 480px) {
    .notif-panel {
        position: fixed;
        top: var(--header-height);
        right: 8px;
        left: 8px;
        width: auto;
        max-width: none;
    }
}

a {
    color: inherit;
}

.app-shell {
    display: flex;
    min-height: 100vh;
}

/* ---------- Sidebar ---------- */

.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    background: var(--sidebar-bg);
    border-right: 1px solid var(--sidebar-border);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    transition: transform 0.2s ease;
}

.sidebar-brand {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    height: var(--header-height);
    padding: 0 24px;
    border-bottom: 1px solid var(--sidebar-border);
    flex-shrink: 0;
}

.sidebar-brand .brand-logo {
    height: 22px;
    width: auto;
    display: block;
}

.sidebar-brand .brand-sub {
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--sidebar-muted-dim);
    margin-top: 4px;
}

.sidebar-nav {
    flex: 1;
    padding: 16px 12px;
    overflow-y: auto;
}

.sidebar-section-label {
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--sidebar-muted-dim);
    padding: 8px 12px 6px;
}

.nav-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 8px;
    font-size: 16px;
    font-weight: 500;
    color: var(--sidebar-text);
    text-decoration: none;
    margin-bottom: 2px;
    transition: background 0.12s ease, color 0.12s ease;
}

.nav-link svg {
    width: 19px;
    height: 19px;
    flex-shrink: 0;
}

.nav-link:hover {
    background: var(--sidebar-hover);
    color: var(--sidebar-text);
}

.nav-link.is-active {
    background: var(--primary);
    color: #fff;
}

.nav-link.is-active svg {
    color: #fff;
}

.nav-link.is-disabled {
    color: var(--sidebar-muted-dim);
    cursor: default;
    pointer-events: none;
}

.nav-soon {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 9.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sidebar-muted-dim);
    background: var(--sidebar-hover);
    border: 1px solid var(--sidebar-border);
    padding: 2px 6px;
    border-radius: 20px;
}

/* ---------- Sidebar nav groups ---------- */

.nav-group {
    margin-bottom: 2px;
}

.nav-group-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 8px;
    font-size: 16px;
    font-weight: 500;
    color: var(--sidebar-text);
    cursor: pointer;
    list-style: none;
    transition: background 0.12s ease, color 0.12s ease;
}

.nav-group-head::-webkit-details-marker {
    display: none;
}

.nav-group-head svg.navicon {
    width: 19px;
    height: 19px;
    flex-shrink: 0;
}

.nav-group-head:hover {
    background: var(--sidebar-hover);
    color: var(--sidebar-text);
}

.nav-group-head.is-active {
    color: var(--sidebar-text);
}

.nav-group-head .grouplabel {
    flex: 1;
}

.nav-chevron {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
    color: var(--sidebar-muted-dim);
    transition: transform 0.15s ease;
}

.nav-group[open] > .nav-group-head .nav-chevron {
    transform: rotate(90deg);
}

.nav-group-items {
    display: flex;
    flex-direction: column;
    padding-top: 1px;
}

.nav-group-link {
    display: flex;
    align-items: center;
    padding: 7px 12px 7px 34px;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 500;
    color: var(--sidebar-text);
    text-decoration: none;
    margin-bottom: 1px;
    transition: background 0.12s ease, color 0.12s ease;
}

.nav-group-link:hover {
    background: var(--sidebar-hover);
    color: var(--sidebar-text);
}

.nav-group-link.is-active {
    background: var(--primary);
    color: #fff;
}

.nav-group-link.is-disabled {
    color: var(--sidebar-muted-dim);
    cursor: default;
    pointer-events: none;
}

.nav-group-link .nav-soon {
    margin-left: auto;
}

.nav-badge {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    background: var(--accent);
    padding: 3px 6px;
    border-radius: 20px;
    min-width: 9px;
    text-align: center;
}

.nav-link.is-active .nav-badge,
.nav-group-link.is-active .nav-badge {
    background: #fff;
    color: var(--primary);
}

/* Plain label pill ("New") rather than an unread count — see
   partials/sidebar.php's badgeText handling. Same shape as
   .nav-badge, just not trying to look like a number that needs
   clearing: no pill-shaped min-width squeeze, a touch more letter
   spacing, uppercase. */
.nav-badge-new {
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 9px;
    padding: 3px 7px;
    min-width: 0;
}

.nav-link.is-active .nav-badge-new,
.nav-group-link.is-active .nav-badge-new {
    background: #fff;
    color: var(--primary);
}

.sidebar-footer {
    padding: 16px 20px 18px;
    border-top: 1px solid var(--sidebar-border);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.sidebar-user {
    line-height: 1.35;
}

.sidebar-user-name {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    color: var(--sidebar-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-user-role {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
}

/* Account identity block — sits directly above .sidebar-signout below
   (moved here from the topbar, partials/header.php — see that
   partial's own comment on why). Own name rather than reusing
   .sidebar-user/.sidebar-user-name above: those are unused elsewhere
   in this app and have no avatar slot of their own. */
.sidebar-account {
    display: flex;
    align-items: center;
    gap: 10px;
}

.sidebar-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    flex-shrink: 0;
    object-fit: cover;
    background: var(--primary-tint);
    border: 1px solid var(--sidebar-border);
}

.sidebar-account-meta {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    min-width: 0;
}

.sidebar-account-name {
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--sidebar-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-account-email {
    font-size: 11.5px;
    color: var(--sidebar-muted-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-signout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: var(--sidebar-text);
    text-decoration: none;
    background: var(--sidebar-hover);
    border: 1px solid var(--sidebar-border);
    border-radius: 8px;
    padding: 9px 12px;
    transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
}

.sidebar-signout svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

/* Solid --danger fill on hover, not a translucent tint over it — a
   light tint of --danger over a white sidebar reads as pale pink, not
   enough contrast for the white icon/text staying on top of it. */
.sidebar-signout:hover {
    border-color: var(--danger);
    color: #fff;
    background: var(--danger);
}

.sidebar-copyright {
    padding-top: 12px;
    border-top: 1px solid var(--sidebar-border);
    font-family: var(--font-body);
    font-size: 10.5px;
    line-height: 1.4;
    color: var(--sidebar-muted-dim);
}

/* ---------- Main column ---------- */

.main-column {
    flex: 1;
    /* Without this, a flex row item defaults to min-width: auto, which
       means it refuses to shrink narrower than the min-content width of
       whatever's nested inside .content (a wide table, an unwrapped
       button row, etc). On mobile that silently grows this column (and
       the whole .app-shell) past the viewport; because .content is
       centered with margin:0 auto *inside* that oversized box, and the
       page loads scrolled to the left edge, what's visible is the left
       overhang — the entire page reads as shifted right. This forces
       the column to actually shrink to the real viewport width instead,
       so any individual wide element overflows (and gets clipped/
       scrolled) locally rather than blowing out the whole shell. */
    min-width: 0;
    margin-left: var(--sidebar-width);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* ---------- Header ---------- */

.topbar {
    height: var(--header-height);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 28px;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
    position: sticky;
    top: 0;
    z-index: 20;
}

.sidebar-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink);
    cursor: pointer;
}

.sidebar-toggle svg {
    width: 18px;
    height: 18px;
}

.topbar-title {
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.topbar-spacer {
    flex: 1;
}

.topbar-user {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-left: 16px;
    border-left: 1px solid var(--line);
}

.logout-link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid var(--line);
    color: var(--muted);
    text-decoration: none;
    transition: border-color 0.12s ease, color 0.12s ease;
}

.logout-link svg {
    width: 16px;
    height: 16px;
}

.logout-link:hover {
    border-color: var(--danger);
    color: var(--danger);
}

/* ---------- Content ---------- */

.content {
    flex: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    box-sizing: border-box;
    padding: 32px 28px 40px;
}

/* ---------- Dashboard home ---------- */

.page-welcome {
    margin: 0 0 28px;
}

.page-welcome h2 {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
}

.page-welcome p {
    color: var(--muted);
    font-size: 14px;
    margin: 0;
}

/* ---------- Custom Build CTA (Servers page) ----------
   Blue-to-teal gradient pill (no navy — see this file's own top
   comment on dropping dark surfaces everywhere) so it reads as a
   premium, standalone action rather than a plain .btn — this is the
   one entry point into the custom-server slider builder, so it's
   meant to stand out against the plain white rack cards below it, not
   blend in with them. Cog icon spins slowly on hover as a small "this
   configures something" cue. */
.custom-build-cta {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
    padding: 12px 22px 12px 18px;
    border: none;
    border-radius: 999px;
    background: linear-gradient(120deg, var(--primary-shade), var(--primary) 60%, var(--accent));
    color: #fff;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 2px 4px rgba(11, 27, 59, .12), 0 12px 24px -8px rgba(29, 78, 216, .55);
    transition: transform .16s ease, box-shadow .16s ease, filter .16s ease;
}

.custom-build-cta:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 10px rgba(11, 27, 59, .16), 0 18px 32px -10px rgba(29, 78, 216, .6);
    filter: brightness(1.04);
    color: #fff;
}

.custom-build-cta:active {
    transform: translateY(0);
    box-shadow: 0 2px 4px rgba(11, 27, 59, .14), 0 8px 16px -8px rgba(29, 78, 216, .55);
}

.custom-build-cta-icon {
    display: flex;
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    color: #fff;
    transition: transform .5s ease;
}

.custom-build-cta:hover .custom-build-cta-icon {
    transform: rotate(75deg);
}

.custom-build-cta-icon svg {
    width: 100%;
    height: 100%;
}

/* ---------- Overview tiles (billing-style) ---------- */

.tiles {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}

@media (max-width: 900px) {
    .tiles {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 480px) {
    .tiles {
        grid-template-columns: 1fr;
    }
}

.tile {
    display: flex;
    align-items: stretch;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: var(--shadow);
    text-decoration: none;
    color: #fff;
    border: none;
    transition: filter 0.15s ease, transform 0.1s ease;
}

a.tile:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
}

.tile-icon {
    width: 64px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.14);
}

.tile-icon svg {
    width: 26px;
    height: 26px;
}

.tile-body {
    flex: 1;
    padding: 16px 18px;
    min-width: 0;
}

.tile-value {
    font-family: var(--font-display);
    font-size: 25px;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-transform: capitalize;
}

.tile-label {
    font-size: 12px;
    opacity: 0.92;
    margin-top: 3px;
}

.tile-sub {
    font-size: 11px;
    opacity: 0.78;
    margin-top: 5px;
}

.tile-sub.is-overdue {
    opacity: 1;
    font-weight: 600;
}

.tile.c-green { background: var(--success); }
.tile.c-blue { background: var(--primary); }
.tile.c-pink { background: #C23B7A; }
.tile.c-orange { background: var(--warning); }
.tile.c-teal { background: var(--info); }
.tile.c-red { background: var(--danger); }

.tile.tile-placeholder {
    background: var(--surface);
    border: 1px dashed var(--line);
    box-shadow: none;
    color: var(--muted);
}

.tile.tile-placeholder .tile-icon {
    background: var(--surface-raised);
    color: var(--muted);
}

.tile.tile-placeholder .tile-value {
    color: var(--muted);
}

.tile.tile-placeholder .tile-sub {
    font-family: var(--font-mono);
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 1;
}

/* Dashboard overview row: chart card + stacked activity/to-do cards,
   same two-thirds/one-third split as the tiles above collapsing to a
   single column on narrow screens. */
.dash-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
    margin-top: 20px;
}

.dash-side {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

@media (max-width: 980px) {
    .dash-grid {
        grid-template-columns: 1fr;
    }
}

.dash-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-tile);
    overflow: hidden;
}

.dash-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--line);
}

.dash-card-head h3 {
    margin: 0;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--primary);
}

.dash-card-empty,
.dash-chart-empty {
    padding: 40px 18px;
    text-align: center;
    font-size: 13px;
    color: var(--muted);
}

.dash-card-foot {
    padding: 10px 18px;
    border-top: 1px solid var(--line);
    background: var(--surface-raised);
}

.dash-card-foot a {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--primary);
    text-decoration: none;
}

.dash-card-foot a:hover {
    text-decoration: underline;
}

.dash-add-btn {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--primary);
    background: var(--primary-tint);
    border-radius: 7px;
    padding: 6px 12px;
    text-decoration: none;
    white-space: nowrap;
}

.dash-add-btn:hover {
    filter: brightness(0.97);
}

/* Account Overview chart */
.chart-legend {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.chart-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--muted);
}

.chart-swatch {
    width: 9px;
    height: 9px;
    border-radius: 2px;
    display: inline-block;
}

.chart-swatch-invoices { background: var(--primary); }
.chart-swatch-payments { background: var(--accent); }

.dash-chart-wrap {
    padding: 18px 18px 4px;
}

.dash-chart-svg {
    width: 100%;
    height: 200px;
    display: block;
    overflow: visible;
}

.chart-area {
    stroke: none;
    opacity: 0.16;
}

.chart-area-invoices { fill: var(--primary); }
.chart-area-payments { fill: var(--accent); }

.chart-line {
    fill: none;
    stroke-width: 2;
    vector-effect: non-scaling-stroke;
}

.chart-line-invoices { stroke: var(--primary); }
.chart-line-payments { stroke: var(--accent); }

.dash-chart-axis {
    position: relative;
    height: 20px;
    margin: 0 18px 14px;
    font-size: 11px;
    color: var(--muted);
}

.dash-chart-axis span {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    white-space: nowrap;
}

.dash-chart-axis span:first-child {
    transform: translateX(0);
}

.dash-chart-axis span:last-child {
    transform: translateX(-100%);
}

/* Recent Activity list — reuses the header notif-item look-and-feel
   (see .notif-item rules above) inside a plain card instead of a
   dropdown panel. */
.dash-activity-list {
    display: flex;
    flex-direction: column;
    max-height: 320px;
    overflow-y: auto;
}

/* Things To Do mini-list */
.dash-todo-list {
    display: flex;
    flex-direction: column;
}

.dash-todo-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 18px;
    border-bottom: 1px solid var(--line);
}

.dash-todo-item:last-child {
    border-bottom: none;
}

.dash-todo-check {
    flex-shrink: 0;
    width: 17px;
    height: 17px;
    border-radius: 5px;
    border: 1.6px solid var(--line);
    background: var(--surface);
    cursor: pointer;
    padding: 0;
}

.dash-todo-check:hover {
    border-color: var(--primary);
}

.dash-todo-title {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-todo-due {
    flex-shrink: 0;
    font-size: 11px;
    color: var(--muted);
}

.dash-todo-due.is-overdue {
    color: var(--danger);
    font-weight: 600;
}

/* Announcements ticker — a slim marquee banner across the top of the
   dashboard. The track is the announcement list rendered twice back
   to back (see dashboard.php) and scrolled exactly half its own
   width, so the loop point is invisible; --ticker-duration is set
   inline per page load based on how much text there is to read. */
.announce-ticker {
    display: flex;
    align-items: stretch;
    max-width: 100%;
    min-width: 0;
    background: linear-gradient(90deg, var(--primary-shade), var(--primary) 70%, var(--accent));
    border-radius: var(--radius);
    box-shadow: var(--shadow-tile);
    overflow: hidden;
    margin-bottom: 20px;
}

.announce-ticker-badge {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 16px;
    font-family: var(--font-display);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: #fff;
    text-decoration: none;
    background: rgba(255, 255, 255, 0.12);
    white-space: nowrap;
}

.announce-ticker-badge:hover {
    background: rgba(255, 255, 255, 0.18);
}

.announce-ticker-badge svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.announce-ticker-viewport {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    position: relative;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 24px, #000 calc(100% - 32px), transparent);
}

.announce-ticker-track {
    display: flex;
    align-items: center;
    width: max-content;
    white-space: nowrap;
    padding: 0 16px;
    animation: announce-ticker-scroll var(--ticker-duration, 24s) linear infinite;
}

.announce-ticker:hover .announce-ticker-track {
    animation-play-state: paused;
}

@keyframes announce-ticker-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

.announce-ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 12px 4px;
    font-size: 13px;
    font-weight: 500;
    color: #fff;
    text-decoration: none;
    opacity: 0.94;
}

.announce-ticker-item:hover {
    opacity: 1;
    text-decoration: underline;
}

.announce-ticker-pin {
    font-size: 11px;
}

.announce-ticker-sep {
    flex-shrink: 0;
    padding: 0 16px;
    color: rgba(255, 255, 255, 0.4);
    font-size: 10px;
}

@media (prefers-reduced-motion: reduce) {
    .announce-ticker-track {
        animation: none;
        overflow-x: auto;
    }
}

@media (max-width: 640px) {
    .announce-ticker-badge span {
        display: none;
    }
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
}

.stat-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    box-shadow: var(--shadow);
}

.stat-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
}

.stat-label {
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.stat-icon {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: var(--primary-tint);
    color: var(--primary);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.stat-icon svg {
    width: 15px;
    height: 15px;
}

.stat-value {
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.stat-value.is-placeholder {
    color: var(--muted);
}

.stat-value.status-active { color: var(--success); text-transform: capitalize; }
.stat-value.status-suspended,
.stat-value.status-closed { color: var(--danger); text-transform: capitalize; }

.stat-foot {
    font-size: 12.5px;
    color: var(--muted);
}

.stat-foot a {
    color: var(--primary);
    text-decoration: none;
}

.stat-foot a:hover {
    text-decoration: underline;
}

.stat-foot .stat-soon {
    font-family: var(--font-mono);
    font-size: 9.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    padding: 2px 6px;
    border-radius: 20px;
}

/* ---------- Services list ---------- */

.service-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.service-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.service-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

/* Holds the name/price line that used to be .service-row's own flex
   row before the Hosting Details block below needed a second row of
   its own — same content, .service-row itself just went column so a
   hosting service can stack .hosting-block underneath it. */
.service-row-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.service-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.service-name-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.service-name {
    font-family: var(--font-display);
    font-size: 15.5px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.service-desc {
    margin: 0;
    font-size: 13px;
    color: var(--muted);
    max-width: 56ch;
}

.service-since {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.service-renews {
    /* Same treatment as .service-since just above — this just reads
       services.nextDueDate instead of createdAt. Deliberately not
       reusing .domain-expiry's is-soon/is-expired color variants:
       those exist because a domain can lapse and stop resolving, a
       service on a card renewal (Renew button, not auto-charged)
       doesn't have that same live-outage stake, so there's no need to
       alarm-color it as its date approaches. */
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

/* Server OS / Control Panel tags — VPS-group active services only,
   see services.php's $serverOsLabel/$serverSoftwareLabel. Same plain
   "label: value" chip shape as .service-since/.service-renews above,
   just two side-by-side instead of one line. */
.service-server-details {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
}

.service-server-detail {
    font-size: 11px;
    color: var(--muted);
}

.service-server-detail-label {
    font-weight: 600;
    color: var(--text);
    margin-right: 3px;
}

.service-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: capitalize;
    letter-spacing: 0.04em;
    padding: 2px 9px;
    border-radius: 20px;
    border: 1px solid transparent;
}

.service-pill.status-active {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.service-pill.status-paused {
    color: var(--warning);
    background: var(--warning-tint);
    border-color: rgba(183, 121, 31, 0.25);
}

.service-pill.status-cancelled {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
}

/* Server Status page's three-colour set — .status-active (green) and
   .status-paused (orange, above) already exist for hosting services;
   these two add green "Online"/red "Offline" for servers specifically,
   since .status-cancelled renders grey rather than red. */
.service-pill.status-online {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.service-pill.status-offline {
    color: var(--danger);
    background: var(--danger-tint);
    border-color: rgba(192, 57, 43, 0.25);
}

/* Best-guess server power status dot (billing_data.php's
   server_power_state()) — separate from the .service-pill billing
   status just to its left. Reuses the same --success/--danger/
   --warning tokens as .service-pill.status-online/offline just above,
   for a consistent green/red/orange meaning across the app. Kept live
   without a reload by the matching JS in partials/footer.php. */
.server-power-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--muted);
}

.server-power-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.server-power-on .server-power-dot {
    background: var(--success);
    box-shadow: 0 0 0 3px var(--success-tint);
}

.server-power-off .server-power-dot {
    background: var(--danger);
    box-shadow: 0 0 0 3px var(--danger-tint);
}

.server-power-rebooting .server-power-dot {
    background: var(--warning);
    box-shadow: 0 0 0 3px var(--warning-tint);
    animation: server-power-pulse 1.1s ease-in-out infinite;
}

@keyframes server-power-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

.server-power-on .server-power-label { color: var(--success); }
.server-power-off .server-power-label { color: var(--danger); }
.server-power-rebooting .server-power-label { color: var(--warning); }

@media (prefers-reduced-motion: reduce) {
    .server-power-rebooting .server-power-dot {
        animation: none;
    }
}

.empty-state {
    background: var(--surface);
    border: 1px dashed var(--line);
    border-radius: 12px;
    padding: 48px 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    color: var(--muted);
    font-size: 14px;
}

.empty-state-icon {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--surface-raised);
    color: var(--muted);
    display: flex;
    align-items: center;
    justify-content: center;
}

.empty-state-icon svg {
    width: 18px;
    height: 18px;
}

@media (max-width: 640px) {
    .service-row-top {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }
}

/* Hosting Details — the domain/server/package facts + quick-action
   links services.php renders under an active service that has a
   hosting_accounts row (hosting_data.php's client_hosting_account()).
   Sits inside .service-row as a second stacked block below
   .service-row-top, separated by its own top border rather than the
   card's own edge, so it reads as "more about this service" rather
   than a second unrelated card. */
.hosting-block {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
}

.hosting-details {
    display: flex;
    flex-wrap: wrap;
    gap: 14px 28px;
}

.hosting-detail {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.hosting-detail-label {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
}

.hosting-detail-value {
    font-size: 12.5px;
    font-weight: 500;
    color: var(--ink);
    word-break: break-word;
}

.hosting-detail-mono {
    font-family: var(--font-mono);
    letter-spacing: 0.01em;
}

/* The Access button (.hosting-access-manage, same .domain-manage
   toggle+panel chrome as domains.php's Manage and the server-power
   menu above) otherwise sits at the LEFT edge of its .hosting-block
   column — .domain-manage's own align-self: flex-start (further down
   this file) pins it there by default, same as it does for the
   server-power Manage button in .price-card. Overridden here to sit
   at the RIGHT edge instead, matching domains.php's Manage button,
   which lives inside .domain-side (that page's own right-pinning
   wrapper) rather than using .domain-manage's plain default. Moving
   the button over also fixes .domain-manage-panel's shared default
   anchor (right: 0, opening leftward) — that anchor needs the button
   to already be near the actual right edge to land on-screen, which
   is now true here too, same as it already was on domains.php, so no
   panel-side override is needed.

   Selector is doubled up (.hosting-access-manage.domain-manage) rather
   than just .hosting-access-manage: this button carries both classes,
   and .domain-manage's own align-self: flex-start (line ~5868) has the
   same specificity but sits later in this file, so a single-class rule
   here loses the cascade and the button stays pinned left. The doubled
   selector outranks it regardless of source order. */
.hosting-access-manage.domain-manage {
    align-self: flex-end;
}

/* Access dropdown menu items — Login to cPanel/WHM/Webmail/File
   Manager/WordPress/SitePad/Show Password, consolidated under the
   services.php "Access" .domain-manage dropdown (see that page's own
   comment above the menu). The dropdown chrome itself (.domain-manage,
   .domain-manage-toggle, .domain-manage-panel, .domain-manage-item)
   is shared with domains.php and the server power menu further up
   this file — only the tinted icon-color variants below are specific
   to hosting access links. */
.hosting-action-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    background: var(--primary-tint);
    color: var(--primary);
}

.hosting-action-icon svg {
    width: 12.5px;
    height: 12.5px;
}

.hosting-action-icon.is-cpanel { background: var(--primary-tint); color: var(--primary); }
.hosting-action-icon.is-whm { background: var(--accent-tint); color: var(--accent); }
.hosting-action-icon.is-webmail { background: var(--info-tint); color: var(--info); }
.hosting-action-icon.is-files { background: var(--success-tint); color: var(--success); }
.hosting-action-icon.is-wordpress { background: var(--warning-tint); color: var(--warning); }
.hosting-action-icon.is-password { background: var(--danger-tint); color: var(--danger); }
.hosting-action-icon.is-sitepad { background: var(--primary-tint); color: var(--primary); }

/* Revealed cPanel password + status line for the "Show Password"
   button above — kept separate from .hosting-actions itself since
   these sit full-width beneath the button row rather than as another
   pill in it. */
.hosting-password-reveal {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 12px;
    border-radius: 9px;
    border: 1px solid var(--line);
    background: var(--surface-alt, var(--surface));
}

.hosting-password-reveal-label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
}

.hosting-password-reveal-value {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink);
    word-break: break-all;
}

.hosting-password-status {
    display: block;
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--muted);
}

.hosting-password-status.is-error {
    color: var(--danger);
}

/* ---------- Invoices list ---------- */

.invoice-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.invoice-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.invoice-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

.invoice-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.invoice-name-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.invoice-number {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.02em;
}

.invoice-desc {
    margin: 0;
    font-size: 13px;
    color: var(--muted);
    max-width: 56ch;
}

.invoice-date {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.invoice-date.is-overdue {
    color: var(--danger);
}

.invoice-amount {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 600;
    flex-shrink: 0;
    white-space: nowrap;
}

.invoice-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: capitalize;
    letter-spacing: 0.04em;
    padding: 3px 10px;
    border-radius: 20px;
    border: 1px solid transparent;
    box-shadow: 0 1px 2px rgba(11, 27, 59, .08);
}

.invoice-pill.status-paid {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.invoice-pill.status-unpaid {
    color: var(--info);
    background: var(--info-tint);
    border-color: rgba(58, 110, 165, 0.25);
}

.invoice-pill.status-overdue {
    color: var(--danger);
    background: var(--danger-tint);
    border-color: rgba(192, 57, 43, 0.25);
}

/* ---------- Funds / wallet ledger (reuses .invoice-list/.invoice-row) ---------- */

.invoice-pill.type-credit {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.invoice-pill.type-debit {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
}

.invoice-amount.is-credit {
    color: var(--success);
}

.wallet-balance-after {
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 400;
    color: var(--muted);
    margin-top: 2px;
}

.funds-balance-tile-row {
    margin-bottom: 24px;
}

.add-funds-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 20px;
    box-shadow: var(--shadow);
    margin-bottom: 28px;
    max-width: 480px;
}

.add-funds-title {
    margin: 0 0 6px;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 600;
}

.add-funds-card .order-field-hint {
    margin: 0 0 16px;
}

.add-funds-form {
    display: flex;
    align-items: flex-end;
    gap: 14px;
    flex-wrap: wrap;
}

.add-funds-field {
    flex: 1 1 160px;
    margin: 0;
}

.add-funds-submit {
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .invoice-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .invoice-amount {
        align-self: flex-end;
    }
}

/* ---------- Orders list ---------- */

.order-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.order-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.order-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

.order-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.order-name-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.order-number {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.order-item-name {
    font-family: var(--font-display);
    font-size: 15.5px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.order-desc {
    margin: 0;
    font-size: 13px;
    color: var(--muted);
    max-width: 56ch;
}

.order-date {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

/* Superseded by .price-card below — orders.php now uses that shared
   class. Left unused pending cleanup. */
.order-price {
    display: flex;
    align-items: baseline;
    gap: 4px;
    flex-shrink: 0;
    white-space: nowrap;
    background: var(--primary-tint);
    border: 1px solid rgba(29, 78, 216, 0.16);
    border-radius: 10px;
    padding: 9px 14px;
}

.order-trailing {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    flex-shrink: 0;
}

.order-invoice-link {
    font-size: 12px;
    font-weight: 600;
    color: var(--primary);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.order-invoice-link:hover {
    border-bottom-color: currentColor;
}

.order-price-value {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    color: var(--primary);
}

.order-price-suffix {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--primary);
    opacity: 0.72;
}

/* ---------- Shared price card + inline action button ---------- */
/* Used anywhere a row needs to show "price + a link to its invoice/
   details" as a compact unit — My Orders, My Services, Funds
   transactions, and the store order-success popup. Replaces plain
   price text + a bare text link with a small self-contained card and
   a real button, so the trailing edge of each row reads as one
   deliberate unit instead of two loose pieces of text. */
.price-card {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
    flex-shrink: 0;
}

.price-card-chip {
    display: flex;
    align-items: baseline;
    gap: 5px;
    white-space: nowrap;
    background: linear-gradient(160deg, var(--primary-tint), var(--surface-raised));
    border: 1px solid rgba(29, 78, 216, 0.2);
    border-radius: 12px;
    padding: 10px 16px;
    box-shadow: 0 1px 2px rgba(11, 27, 59, .06), 0 8px 18px -10px rgba(29, 78, 216, .45);
}

.price-card-value {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    color: var(--primary);
}

.price-card-suffix {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--primary);
    opacity: 0.65;
}

.price-card-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--primary);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 9px;
    padding: 7px 13px;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(11, 27, 59, .04);
    transition: border-color 0.12s ease, background 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
}

.price-card-btn svg {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
}

.price-card-btn:hover {
    border-color: var(--primary);
    background: var(--primary-tint);
    box-shadow: 0 6px 14px -8px rgba(29, 78, 216, .45);
    transform: translateY(-1px);
}

.price-card-btn:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(11, 27, 59, .04);
}

@media (max-width: 640px) {
    .price-card {
        align-self: flex-end;
        align-items: flex-end;
    }
}

.order-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: capitalize;
    letter-spacing: 0.04em;
    padding: 2px 9px;
    border-radius: 20px;
    border: 1px solid transparent;
}

.order-pill.status-pending {
    color: var(--warning);
    background: var(--warning-tint);
    border-color: rgba(183, 121, 31, 0.25);
}

.order-pill.status-active {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.order-pill.status-cancelled {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
}

@media (max-width: 640px) {
    .order-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .order-trailing {
        align-self: flex-end;
        align-items: flex-end;
    }
}

/* ---------- Invoice detail ---------- */

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
    text-decoration: none;
    margin-bottom: 20px;
    transition: color 0.12s ease;
}

.back-link svg {
    width: 14px;
    height: 14px;
}

.back-link:hover {
    color: var(--ink);
}

.invoice-detail-card {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    padding: 32px;
    max-width: 720px;
    margin: 0 auto;
    box-shadow: var(--shadow-elevated);
    overflow: hidden;
}

.invoice-detail-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 5px;
    background: linear-gradient(90deg, var(--primary), var(--accent));
}

.detail-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding-bottom: 22px;
    margin-bottom: 22px;
    border-bottom: 1px solid var(--line);
}

.detail-eyebrow {
    display: block;
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    margin-bottom: 4px;
}

.detail-number {
    font-family: var(--font-display);
    font-size: 24px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0;
}

.detail-header-right {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.print-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--ink);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 7px 12px;
    cursor: pointer;
    box-shadow: var(--shadow-tile);
    transition: border-color 0.12s ease, transform 0.12s ease, box-shadow 0.12s ease;
}

.print-btn svg {
    width: 14px;
    height: 14px;
}

.print-btn:hover {
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: var(--shadow-tile-hover);
}

.print-btn:active {
    transform: translateY(0);
    box-shadow: var(--shadow-tile);
}

@media (max-width: 640px) {
    /* The previous fix here (flex-wrap on both .detail-header and
       .detail-header-right) relied on the three items — status pill,
       Pay button, Print button — happening to be narrow enough to wrap
       cleanly within whatever width was left. That's fragile: a larger
       invoice total ("Pay GHS 12,450.00"), a longer status label, or a
       user with browser text-zoom turned up can still add up to more
       than one row's width and push Print (the last item) part-way off
       the card instead of onto a clean new line — which is exactly
       what was being reported as "the print button hides/shifts off
       screen". Stacking every item in the right-hand cluster at a
       guaranteed 100% width removes the wrap math entirely: each item
       gets the full row to itself regardless of how long its text is,
       so nothing can ever overflow sideways here again. */
    .detail-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .detail-header-right {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
    }

    .invoice-pill {
        align-self: flex-start;
    }

    .pay-btn,
    .print-btn {
        width: 100%;
        justify-content: center;
    }

    /* 32px of padding on each side was eating a big share of an
       already-narrow phone screen (e.g. ~90px combined on a 320px-wide
       device once .content's own mobile padding is subtracted too),
       leaving less room for the table/meta content than necessary. */
    .invoice-detail-card {
        padding: 20px;
    }
}

.detail-meta-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 20px;
    margin-bottom: 26px;
}

.meta-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.meta-label {
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
}

.meta-value {
    font-size: 14px;
    font-weight: 500;
}

.meta-value.is-overdue {
    color: var(--danger);
}

.meta-sub {
    font-size: 12px;
    color: var(--muted);
}

.detail-table {
    width: 100%;
    border-collapse: collapse;
}

.detail-table th {
    text-align: left;
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 500;
    padding: 0 0 10px;
    border-bottom: 1px solid var(--line);
}

.detail-table td {
    padding: 14px 0;
    font-size: 14px;
    border-bottom: 1px solid var(--line);
}

.detail-table tfoot td {
    border-bottom: none;
    padding-top: 18px;
    padding-bottom: 4px;
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 700;
}

.detail-table tfoot .detail-table-amount {
    color: var(--primary);
}

.detail-table-amount {
    text-align: right;
    white-space: nowrap;
}

.no-print {
    display: inline-flex;
}

@media print {
    .sidebar,
    .topbar,
    .app-footer,
    .no-print {
        display: none !important;
    }

    .main-column {
        margin-left: 0;
    }

    body,
    .content {
        background: #fff;
        color: #111;
    }

    .invoice-detail-card {
        border: none;
        padding: 0;
        max-width: none;
        box-shadow: none;
    }

    .invoice-detail-card::before {
        display: none;
    }

    .invoice-pill {
        box-shadow: none;
    }
}

/* Matches .store-order-btn/.order-btn-primary — same flat-fill,
   blue-glow treatment as every other primary action button in the
   client area, in place of the old skeuomorphic gradient/bottom-shadow
   look. */
.pay-btn {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: #fff;
    background: var(--primary);
    border: 1px solid var(--primary);
    border-radius: 10px;
    padding: 11px 18px;
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 6px 14px -6px rgba(29, 78, 216, .55);
    transition: filter 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.pay-btn:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
    box-shadow: 0 10px 20px -8px rgba(29, 78, 216, .6);
}

.pay-btn:active {
    transform: translateY(0);
    box-shadow: 0 4px 10px -6px rgba(29, 78, 216, .5);
}

.pay-btn:disabled,
.payment-method-tile:disabled {
    opacity: 0.6;
    cursor: default;
    pointer-events: none;
}

.payment-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 13.5px;
    font-weight: 500;
    padding: 12px 16px;
    border-radius: 12px;
    margin: 0 auto 20px;
    max-width: 720px;
    box-shadow: var(--shadow-tile);
}

.payment-banner svg {
    width: 17px;
    height: 17px;
    flex-shrink: 0;
    padding: 5px;
    box-sizing: content-box;
    border-radius: 50%;
    background: rgba(255, 255, 255, .55);
    box-shadow: 0 1px 2px rgba(11, 27, 59, .12);
}

.payment-banner-logo {
    width: 19px;
    height: 19px;
    flex-shrink: 0;
    padding: 4px;
    box-sizing: content-box;
    border-radius: 50%;
    background: rgba(255, 255, 255, .55);
    box-shadow: 0 1px 2px rgba(11, 27, 59, .12);
    object-fit: contain;
}

html[data-theme="dark"] .payment-banner svg {
    background: rgba(255, 255, 255, .06);
}

html[data-theme="dark"] .payment-banner-logo {
    background: rgba(255, 255, 255, .06);
}

.payment-banner.is-success {
    color: var(--success);
    background: var(--success-tint);
    border: 1px solid rgba(30, 142, 90, 0.25);
}

.payment-banner.is-failed {
    color: var(--danger);
    background: var(--danger-tint);
    border: 1px solid rgba(192, 57, 43, 0.25);
}

.payment-banner-action {
    margin-left: auto;
    flex-shrink: 0;
    font-weight: 600;
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid currentColor;
    white-space: nowrap;
}

.payment-banner-action:hover {
    opacity: 0.8;
}

/* ---------- Invoice — payment methods + manual payment modal ---------- */

.payment-methods {
    display: block;
    margin-bottom: 26px;
}

.payment-methods-label {
    display: block;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    margin-bottom: 10px;
}

.content-subsection-label {
    display: block;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    margin: 32px 0 12px;
}

.payment-methods-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    gap: 8px;
}

.payment-method-tile {
    display: flex;
    align-items: center;
    gap: 9px;
    text-align: left;
    text-decoration: none;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 8px 10px;
    cursor: pointer;
    font-family: var(--font-body);
    color: var(--ink);
    box-shadow: var(--shadow-tile);
    transition: border-color 0.12s ease, transform 0.16s ease, box-shadow 0.16s ease;
}

.payment-method-tile:hover {
    border-color: var(--primary);
    transform: translateY(-2px);
    box-shadow: var(--shadow-tile-hover);
}

.payment-method-tile:active {
    transform: translateY(0);
    box-shadow: var(--shadow-tile);
}

.payment-method-tile.is-automatic {
    border-color: var(--primary);
    background: linear-gradient(180deg, var(--primary-tint) 0%, var(--surface-raised) 100%);
}

.payment-method-tile.is-pref {
    border-color: var(--success);
    box-shadow: 0 0 0 1.5px var(--success-tint);
}

.pm-tile-title-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.pm-tile-badge {
    font-family: var(--font-mono);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--success);
    background: var(--success-tint);
    border: 1px solid rgba(30, 142, 90, 0.25);
    border-radius: 20px;
    padding: 1px 7px;
    flex-shrink: 0;
}

.default-method-choice {
    position: relative;
}

.default-method-choice .default-method-radio {
    position: absolute;
    top: 8px;
    right: 8px;
    margin: 0;
    accent-color: var(--success);
}

.default-method-choice.is-selected {
    border-color: var(--success);
    box-shadow: 0 0 0 1.5px var(--success-tint);
}

.paymethod-default-hint {
    margin: -4px 0 12px;
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--muted);
}

.pm-logo {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    background: #FFFFFF;
    border: 1px solid var(--line);
    padding: 4px;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(11, 27, 59, .1), 0 1px 0 rgba(255, 255, 255, .8) inset;
}

.pm-logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.pm-tile-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.pm-tile-title {
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pm-tile-sub {
    font-size: 10.5px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Modal */

.pm-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(11, 27, 59, 0.45);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    z-index: 100;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s ease;
}

.pm-modal-overlay[hidden] {
    display: none;
}

.pm-modal-overlay.is-open {
    opacity: 1;
    visibility: visible;
}

/* On desktop the sidebar (--sidebar-width, fixed) sits on top of this
   overlay, so centering against inset:0 (the whole viewport) visually
   pulls the modal toward the sidebar instead of the actual content
   area next to it. Offsetting the overlay's left edge past the
   sidebar — same >900px breakpoint the sidebar itself uses to go
   off-canvas on mobile (see ".sidebar" in the Mobile section below) —
   makes the flex centering land in the middle of the visible content
   instead. */
@media (min-width: 901px) {
    .pm-modal-overlay {
        left: var(--sidebar-width);
    }
}

.pm-modal {
    position: relative;
    width: 100%;
    max-width: 380px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    box-shadow: var(--shadow-elevated);
    padding: 30px 26px 26px;
    transform: scale(0.94) translateY(8px);
    opacity: 0;
    transition: transform 0.22s cubic-bezier(.22, .85, .32, 1.1), opacity 0.18s ease;
}

.pm-modal-overlay.is-open .pm-modal {
    transform: scale(1) translateY(0);
    opacity: 1;
}

.pm-modal-overlay.is-closing .pm-modal {
    transform: scale(0.96) translateY(4px);
    opacity: 0;
}

.pm-modal-close {
    position: absolute;
    top: 14px;
    right: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: none;
    background: var(--surface-raised);
    border-radius: 9px;
    color: var(--muted);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.pm-modal-close:hover {
    background: var(--danger-tint);
    color: var(--danger);
}

.pm-modal-close svg {
    width: 14px;
    height: 14px;
}

.pm-modal-logo {
    width: 46px;
    height: 46px;
    border-radius: 13px;
    margin-bottom: 14px;
    background: #FFFFFF;
    border: 1px solid var(--line);
    padding: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    box-shadow: 0 3px 8px -2px rgba(11, 27, 59, 0.16), 0 0 0 4px var(--primary-tint);
}

.pm-modal-logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.pm-modal-eyebrow {
    display: block;
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--accent);
    margin-bottom: 5px;
}

.pm-modal-title {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 600;
    color: var(--ink);
    margin: 0 0 18px;
}

.pm-modal-rows {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 18px;
}

.pm-modal-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 12px 14px;
    transition: border-color 0.12s ease, background 0.12s ease;
}

.pm-modal-row:hover {
    border-color: var(--primary);
}

.pm-modal-row-label {
    display: block;
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
    margin-bottom: 3px;
}

.pm-modal-row-value {
    display: block;
    font-family: var(--font-mono);
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: 0.02em;
}

.pm-copy-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-body);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--primary);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 7px 11px;
    cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
}

.pm-copy-btn:hover {
    border-color: var(--primary);
    background: var(--primary-tint);
}

.pm-copy-btn.is-copied {
    color: var(--success);
    border-color: var(--success);
    background: var(--success-tint);
}

.pm-copy-btn svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

.pm-copy-icon-check {
    display: none;
}

.pm-copy-btn.is-copied .pm-copy-icon-copy {
    display: none;
}

.pm-copy-btn.is-copied .pm-copy-icon-check {
    display: block;
}

.pm-modal-note {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--info-tint);
    border: 1px solid rgba(58, 110, 165, 0.18);
    border-radius: 12px;
    padding: 12px 14px;
    margin: 0;
}

.pm-modal-note-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    margin-top: 1px;
}

.pm-modal-note p {
    margin: 0;
    font-size: 12px;
    color: var(--muted);
    line-height: 1.5;
}

.pm-modal-note strong {
    color: var(--ink);
    font-weight: 700;
}

/* ---------- Domains — Manage Nameservers modal ---------- */
/* Reuses .pm-modal-overlay/.pm-modal/.pm-modal-close/.pm-modal-eyebrow/
   .pm-modal-title/.pm-modal-note from the payment-methods modal above
   — only the wider max-width and the form-specific bits below are new. */

.ns-modal {
    max-width: 420px;
}

.ns-modal-form {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-bottom: 18px;
}

/* Default-vs-custom nameserver choice on order.php's Configure step —
   reuses .ns-field-grid/.ns-field below for the revealed custom-host
   inputs, same as the post-registration Manage Nameservers modal. */
.ns-mode-choice {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}

.ns-mode-option {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: 13.5px;
    color: var(--ink);
    cursor: pointer;
}

.ns-mode-option input[type="radio"] {
    margin-top: 3px;
    accent-color: var(--primary);
    flex-shrink: 0;
}

.ns-mode-option span em {
    font-style: normal;
    color: var(--muted);
}

.ns-field-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

.ns-field-grid.is-hidden {
    display: none;
}

@media (max-width: 480px) {
    .ns-field-grid {
        grid-template-columns: 1fr;
    }
}

.ns-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.ns-field span {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
}

.ns-field span em {
    font-style: normal;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.75;
}

.ns-field input {
    font-family: var(--font-mono);
    font-size: 13px;
    color: var(--ink);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px 12px;
    transition: border-color 0.12s ease;
}

.ns-field input:focus {
    outline: none;
    border-color: var(--primary);
}

.ns-modal-status {
    font-size: 12px;
    line-height: 1.5;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--danger-tint);
    color: var(--danger);
}

.ns-modal-status.is-success {
    background: var(--success-tint);
    color: var(--success);
}

.ns-modal-submit {
    width: 100%;
}

.ns-modal-submit:disabled {
    opacity: 0.65;
    cursor: default;
}

/* ---------- Messages list ---------- */

.message-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.message-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.message-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

.message-row.is-unread {
    border-color: rgba(29, 78, 216, 0.35);
    background: var(--primary-tint);
}

.message-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.message-subject-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.message-subject {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.message-row.is-unread .message-subject {
    color: var(--primary-dark);
}

.message-unread-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--primary);
    flex-shrink: 0;
}

.message-snippet {
    margin: 0;
    font-size: 13px;
    color: var(--muted);
    max-width: 62ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.message-meta {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.message-from {
    flex-shrink: 0;
    white-space: nowrap;
    text-align: right;
    font-size: 12.5px;
    color: var(--muted);
}

.message-from .message-pill {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 9px;
    border-radius: 20px;
    border: 1px solid rgba(58, 110, 165, 0.25);
    color: var(--info);
    background: var(--info-tint);
}

@media (max-width: 640px) {
    .message-row {
        flex-direction: column;
        /* .message-row's base rule sets align-items: flex-start to
           top-align its two columns in the desktop row layout — that
           same value, left over once flex-direction flips to column
           here, cross-axis-aligns .message-main/.message-from to the
           left instead of stretching them to the card's width. With
           no stretch, .message-snippet (white-space: nowrap, up to
           62ch) sizes to its own unclamped content width and spills
           past the card edge rather than actually being constrained
           enough for its own overflow/ellipsis rule to kick in. */
        align-items: stretch;
        gap: 10px;
    }

    .message-from {
        text-align: left;
    }
}

/* ---------- Announcements ---------- */

.announcement-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.announcement-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 20px 22px;
    box-shadow: var(--shadow);
}

.announcement-card.is-pinned {
    border-color: rgba(183, 121, 31, 0.4);
    background: linear-gradient(var(--surface), var(--surface)) padding-box,
                var(--warning-tint);
}

.announcement-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 12px;
    margin-bottom: 10px;
}

.announcement-pin-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 3px 9px;
    border-radius: 20px;
    border: 1px solid rgba(183, 121, 31, 0.35);
    color: var(--warning);
    background: var(--warning-tint);
    order: -1;
}

.announcement-pin-badge svg {
    width: 11px;
    height: 11px;
}

.announcement-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.01em;
    flex: 1 1 auto;
    min-width: 0;
}

.announcement-meta {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
    white-space: nowrap;
}

.announcement-body {
    font-size: 14px;
    line-height: 1.65;
    color: var(--ink);
}

@media (max-width: 640px) {
    .announcement-card {
        padding: 16px 18px;
    }

    .announcement-title {
        flex-basis: 100%;
    }
}

/* ---------- Promos & Coupons ----------
   Styled as a physical gold charge card rather than a paper coupon:
   real card proportions (1.586:1), a chip, an issuer wordmark, a
   foil/hologram seal, and the code set like an embossed card number.
   --gold-1..4 run dark bronze -> bright champagne so the sweep reads
   as brushed metal, not a flat color. Pointer-tracked glare/tilt
   (promos.php's inline script sets --rx/--ry/--mx/--my; all the
   animation itself lives here) and a staggered rise-in on load both
   back off under prefers-reduced-motion and on touch/coarse pointers,
   where promos.php skips wiring the tilt listeners entirely. */

.promo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 26px 22px;
    perspective: 1600px;
}

.promo-card {
    --rx: 0deg;
    --ry: 0deg;
    --mx: 50%;
    --my: 0%;
    --glow: 0;
    --gold-1: #2c1e0b;
    --gold-2: #7c5a20;
    --gold-3: #d9ac52;
    --gold-4: #f6e4ac;
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 220px;
    color: #fbf1d9;
    background:
        radial-gradient(140% 120% at 12% -10%, rgba(255, 240, 200, .4) 0%, transparent 45%),
        linear-gradient(128deg, var(--gold-1) 0%, var(--gold-2) 24%, var(--gold-3) 46%, var(--gold-4) 56%, var(--gold-3) 66%, var(--gold-2) 84%, var(--gold-1) 100%);
    background-size: 220% 220%;
    background-position: calc(50% + var(--ry) * 2%) calc(50% - var(--rx) * 2%);
    border: 1px solid rgba(255, 226, 150, .4);
    border-radius: 18px;
    padding: 20px 22px 18px;
    box-shadow:
        0 1px 0 rgba(255, 245, 210, .5) inset,
        0 2px 3px rgba(35, 24, 6, .3),
        0 24px 40px -20px rgba(120, 88, 20, .65);
    transform: perspective(1600px) rotateX(var(--rx)) rotateY(var(--ry)) translateZ(0);
    transform-style: preserve-3d;
    transition: transform .45s cubic-bezier(.22, .9, .3, 1), box-shadow .45s cubic-bezier(.22, .9, .3, 1), background-position .45s cubic-bezier(.22, .9, .3, 1);
    opacity: 0;
    animation: promo-card-in .55s cubic-bezier(.22, .9, .3, 1) forwards;
    animation-delay: calc(var(--i, 0) * 70ms);
    overflow: hidden;
}

html[data-theme="dark"] .promo-card {
    box-shadow:
        0 1px 0 rgba(255, 245, 210, .35) inset,
        0 2px 3px rgba(0, 0, 0, .45),
        0 24px 44px -18px rgba(0, 0, 0, .6),
        0 0 0 1px rgba(255, 224, 140, .06);
}

.promo-card:hover,
.promo-card:focus-within {
    border-color: rgba(255, 232, 170, .7);
    box-shadow:
        0 1px 0 rgba(255, 245, 210, .55) inset,
        0 2px 3px rgba(35, 24, 6, .32),
        0 28px 48px -18px rgba(120, 88, 20, .75);
}

/* Fine brushed-metal striping across the whole face — a repeating
   diagonal texture kept faint enough to read as material, not decor. */
.promo-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        128deg,
        rgba(255, 255, 255, .09) 0px,
        rgba(255, 255, 255, .09) 1px,
        transparent 1px,
        transparent 5px
    );
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 1;
}

/* Pointer-tracked glare sweep — a warm light patch that follows --mx/
   --my, clipped to the card's rounded rect. Only visible once a
   pointerenter has set --glow via the script; stays inert (and
   harmless) if JS never runs. */
.promo-card-shine {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}

.promo-card-shine::after {
    content: "";
    position: absolute;
    inset: -40%;
    background: radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, .65), transparent 42%);
    opacity: var(--glow);
    transition: opacity .35s ease;
}

/* Holographic security seal, corner-anchored like a real card's foil
   sticker — a conic gradient gives the iridescent shift, soft-light
   blending keeps it reading as foil rather than a flat sticker. */
.promo-hologram {
    position: absolute;
    top: 16px;
    right: 18px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: conic-gradient(from 200deg, #f6e4ac, #c9dfe0, #e8c7e8, #f6e4ac, #d9ac52, #f6e4ac);
    mix-blend-mode: soft-light;
    opacity: .8;
    z-index: 1;
    pointer-events: none;
}

.promo-hologram svg {
    width: 100%;
    height: 100%;
    color: rgba(44, 30, 11, .55);
}

.promo-card > .promo-chip,
.promo-card > .promo-card-top,
.promo-card > .promo-amount,
.promo-card > .promo-title,
.promo-card > .promo-desc,
.promo-card > .promo-bottom {
    position: relative;
    z-index: 3;
}

/* Skeuomorphic chip: gold-brass gradient body with the classic
   contact-pad grid etched on top in darker hairlines. */
.promo-chip {
    width: 38px;
    height: 29px;
    border-radius: 6px;
    margin-bottom: 14px;
    background: linear-gradient(155deg, #ecd394 0%, #b5872f 45%, #8a6420 100%);
    border: 1px solid rgba(70, 48, 14, .5);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .4) inset;
    position: relative;
    overflow: hidden;
}

.promo-chip::before {
    content: "";
    position: absolute;
    inset: 4px;
    border: 1px solid rgba(70, 48, 14, .45);
    border-radius: 3px;
    background:
        linear-gradient(rgba(70, 48, 14, .4), rgba(70, 48, 14, .4)) center / 100% 1px no-repeat,
        linear-gradient(rgba(70, 48, 14, .4), rgba(70, 48, 14, .4)) center / 1px 100% no-repeat,
        linear-gradient(rgba(70, 48, 14, .4), rgba(70, 48, 14, .4)) 33% 0 / 1px 100% no-repeat,
        linear-gradient(rgba(70, 48, 14, .4), rgba(70, 48, 14, .4)) 67% 0 / 1px 100% no-repeat;
}

.promo-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: auto;
}

/* Faded gold brand mark, bled off the bottom-right corner — reads like
   the ghost network-logo watermark on a premium card rather than a
   flat sticker. Sits at z-index 1, below the code strip / copy button
   (z-index 3), so it never fights the interactive UI; it just shows
   through the empty gold field around it. Built from the transparent
   Vikalink icon as a CSS mask so it always renders in the card's own
   gold tones with no extra image asset needed. */
.promo-cardmark {
    position: absolute;
    right: -22px;
    bottom: -22px;
    width: 128px;
    height: 128px;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(155deg, var(--gold-4) 0%, #fffbe8 35%, var(--gold-3) 55%, var(--gold-2) 100%);
    -webkit-mask-image: url('vikalink-icon.png');
    mask-image: url('vikalink-icon.png');
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    opacity: .22;
    mix-blend-mode: overlay;
}

html[data-theme="dark"] .promo-cardmark {
    opacity: .28;
    mix-blend-mode: soft-light;
}

.promo-brand {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #fdf3d9;
    text-shadow: 0 1px 0 rgba(35, 24, 6, .4);
}

.promo-expiry {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    font-family: var(--font-mono);
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: rgba(251, 241, 217, .75);
    white-space: nowrap;
}

.promo-expiry-value {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    font-weight: 600;
    color: #fdf3d9;
}

.promo-expiry.is-soon .promo-expiry-value {
    color: #ffe4b0;
}

.promo-expiry-dot {
    position: relative;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #ffb84d;
    flex-shrink: 0;
}

.promo-expiry-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: inherit;
    animation: status-pulse 1.8s ease-out infinite;
}

/* The hero figure, set like an embossed balance — big, warm-white,
   with a soft dark drop and a hairline highlight to fake letterpress. */
.promo-amount {
    font-family: var(--font-display);
    font-size: clamp(28px, 7cqw, 38px);
    font-weight: 800;
    letter-spacing: -0.01em;
    color: #fffaec;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .35), 0 2px 2px rgba(35, 24, 6, .45);
    margin: 10px 0 4px;
}

.promo-title {
    margin: 0 0 4px;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: #fdf3d9;
}

.promo-desc {
    margin: 0 0 12px;
    font-size: 12px;
    line-height: 1.5;
    color: rgba(251, 241, 217, .72);
}

.promo-bottom {
    margin-top: auto;
}

/* Coupon code set like the embossed card number — mono, wide
   tracking, gently raised off the metal via the same letterpress
   text-shadow trick used on .promo-amount. */
.promo-code-strip {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 240, 200, .3);
}

.promo-code {
    font-family: var(--font-mono);
    font-size: 17px;
    font-weight: 600;
    letter-spacing: 0.18em;
    color: #fffaec;
    text-shadow: 0 1px 0 rgba(255, 255, 255, .3), 0 1px 1px rgba(35, 24, 6, .4);
    word-break: break-all;
}

.promo-copy-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 600;
    color: #2c1e0b;
    background: rgba(255, 250, 236, .92);
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: 8px;
    padding: 6px 10px;
    cursor: pointer;
    transition: background 0.12s ease, transform 0.12s ease;
}

.promo-copy-btn:hover {
    background: #fff;
    transform: translateY(-1px);
}

.promo-copy-btn:active {
    transform: translateY(0) scale(.96);
}

.promo-copy-btn.is-copied {
    color: #1f4d2e;
    background: #cdeed9;
    animation: promo-copied-pop .4s cubic-bezier(.22, .9, .3, 1);
}

.promo-copy-btn svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

.promo-copy-icon-check {
    display: none;
}

.promo-copy-btn.is-copied .promo-copy-icon-copy {
    display: none;
}

.promo-copy-btn.is-copied .promo-copy-icon-check {
    display: block;
}

.promo-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin-top: 10px;
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: 0.03em;
    color: rgba(251, 241, 217, .65);
}

@keyframes promo-card-in {
    from {
        opacity: 0;
        transform: perspective(1600px) rotateX(6deg) translateY(14px) scale(.97);
    }
    to {
        opacity: 1;
        transform: perspective(1600px) rotateX(var(--rx)) rotateY(var(--ry)) translateY(0) scale(1);
    }
}

@keyframes promo-copied-pop {
    0% { transform: scale(1); }
    40% { transform: scale(1.07); }
    100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .promo-card,
    .promo-plain-card {
        animation: none;
        opacity: 1;
        transition: none;
    }

    .promo-card::before,
    .promo-hologram,
    .promo-copy-btn.is-copied,
    .promo-plain-card::before,
    .promo-plain-seal {
        transition: none;
        animation: none;
    }
}

/* ---------- Promos page (public/promos.php) ----------
   Two card shapes per promo_is_hero(): a full-width hero banner
   (image + CTA all set) modeled on .domain-search-panel's flat
   off-white treatment, or — for anything short of that — a foil card
   the same shape/fields as .announcement-card but decorated like the
   Coupons page's .promo-card (see that section's comment above). */

/* Grid, not a single flex column — same repeat(auto-fill, minmax(300px, 1fr))
   the Coupons page's .promo-grid uses, so plain promo cards land three
   to a row at the same widths coupons.php does instead of stretching
   full-bleed. Hero banners (image + CTA) are the one exception: they
   still want the full row, so .promo-hero-banner spans every column
   below rather than sitting in its own grid cell. */
.promo-feed {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 26px 22px;
    perspective: 1600px;
}

.promo-hero-banner {
    grid-column: 1 / -1;
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 28px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    box-shadow: var(--shadow-elevated);
    padding: 30px 34px;
    overflow: hidden;
}

.promo-hero-banner.is-pinned {
    border-color: rgba(227, 172, 78, 0.6);
}

.promo-hero-banner::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(560px 280px at 100% 0%, var(--primary-tint), transparent 70%);
    pointer-events: none;
}

.promo-hero-media {
    position: relative;
    flex: 0 0 240px;
    border-radius: 14px;
    overflow: hidden;
    background: var(--surface-raised);
}

.promo-hero-media img {
    width: 100%;
    height: 100%;
    min-height: 160px;
    object-fit: cover;
    display: block;
}

.promo-hero-body {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    flex: 1 1 auto;
    min-width: 0;
}

.promo-hero-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 10px;
    margin-bottom: 12px;
}

/* Discount/callout pill on a hero promo (e.g. "20% off") — solid
   filled and glowing so it pops as its own focal point against the
   now-white hero banner rather than reading as a faint outline; the
   warm gold gradient plus glow doubles as the "special offer" cue the
   plain accent-on-glass version lacked. */
.promo-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #2c1e0b;
    background: linear-gradient(135deg, #f6e4ac 0%, #e3ac4e 100%);
    border: 1px solid rgba(255, 244, 214, .6);
    border-radius: 20px;
    padding: 7px 15px 7px 11px;
    box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 4px 12px -3px rgba(227, 172, 78, .55);
}

.promo-hero-badge svg {
    width: 15px;
    height: 15px;
}

.promo-hero-title {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--sidebar-text);
    margin: 0 0 8px;
}

.promo-hero-message {
    font-size: 14px;
    line-height: 1.65;
    color: var(--sidebar-muted);
    margin-bottom: 20px;
}

/* Reuses .store-order-btn (the hosting-plan CTA style) so the promo
   button matches the rest of the client area exactly instead of the
   older .pay-btn treatment. .store-order-btn is written for full-width
   card footers, so this override (higher specificity than the plain
   .store-order-btn rule, so it wins regardless of source order) keeps
   it auto-width and inline with the icon here. */
.promo-hero-cta.store-order-btn {
    display: inline-flex;
    width: auto;
    align-items: center;
    gap: 6px;
    margin-top: auto;
    text-decoration: none;
}

.promo-hero-cta svg {
    width: 14px;
    height: 14px;
}

/* Plain promo card — same foil-card language as .promo-card on the
   Coupons page (brushed gradient sweep, pointer-tracked glare, corner
   seal, bled brand watermark, staggered rise-in), recolored from gold
   into Vikalink's own navy/sapphire/teal so it reads as "campaign
   foil" rather than a redeemable code. Pointer-tracked glare/tilt
   (promos.php's inline script sets --rx/--ry/--mx/--my/--glow; all
   the animation itself lives here) and the staggered rise-in both
   back off under prefers-reduced-motion and on touch/coarse pointers,
   where promos.php skips wiring the tilt listeners entirely. */
.promo-plain-card {
    --rx: 0deg;
    --ry: 0deg;
    --mx: 50%;
    --my: 0%;
    --glow: 0;
    --foil-1: #060b18;
    --foil-2: #0f2a56;
    --foil-3: #1d4ed8;
    --foil-4: #5fd9d3;
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 150px;
    color: #eaf6ff;
    background:
        radial-gradient(140% 120% at 12% -10%, rgba(160, 210, 255, .28) 0%, transparent 45%),
        linear-gradient(128deg, var(--foil-1) 0%, var(--foil-2) 26%, var(--foil-3) 48%, var(--foil-4) 58%, var(--foil-3) 68%, var(--foil-2) 86%, var(--foil-1) 100%);
    background-size: 220% 220%;
    background-position: calc(50% + var(--ry) * 2%) calc(50% - var(--rx) * 2%);
    border: 1px solid rgba(160, 210, 255, .28);
    border-radius: 16px;
    padding: 20px 22px;
    box-shadow:
        0 1px 0 rgba(200, 225, 255, .18) inset,
        0 2px 3px rgba(3, 8, 20, .35),
        0 22px 40px -20px rgba(6, 20, 50, .65);
    transform: perspective(1400px) rotateX(var(--rx)) rotateY(var(--ry)) translateZ(0);
    transform-style: preserve-3d;
    transition: transform .45s cubic-bezier(.22, .9, .3, 1), box-shadow .45s cubic-bezier(.22, .9, .3, 1), background-position .45s cubic-bezier(.22, .9, .3, 1);
    opacity: 0;
    animation: promo-card-in .55s cubic-bezier(.22, .9, .3, 1) forwards;
    animation-delay: calc(var(--i, 0) * 70ms);
    overflow: hidden;
}

html[data-theme="dark"] .promo-plain-card {
    box-shadow:
        0 1px 0 rgba(200, 225, 255, .12) inset,
        0 2px 3px rgba(0, 0, 0, .5),
        0 24px 44px -18px rgba(0, 0, 0, .7),
        0 0 0 1px rgba(160, 210, 255, .05);
}

.promo-plain-card:hover,
.promo-plain-card:focus-within {
    border-color: rgba(180, 220, 255, .5);
    box-shadow:
        0 1px 0 rgba(200, 225, 255, .28) inset,
        0 2px 3px rgba(3, 8, 20, .38),
        0 26px 48px -18px rgba(6, 20, 50, .78);
}

.promo-plain-card.is-pinned {
    border-color: rgba(227, 172, 78, 0.55);
    box-shadow:
        0 1px 0 rgba(200, 225, 255, .18) inset,
        0 2px 3px rgba(3, 8, 20, .35),
        0 0 0 1px rgba(227, 172, 78, .3),
        0 22px 40px -20px rgba(6, 20, 50, .65);
}

/* Fine brushed texture across the whole face, same trick as the
   coupon card's ::before. */
.promo-plain-card::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        128deg,
        rgba(255, 255, 255, .05) 0px,
        rgba(255, 255, 255, .05) 1px,
        transparent 1px,
        transparent 5px
    );
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 1;
}

/* Pointer-tracked glare sweep — a cool light patch that follows
   --mx/--my, clipped to the card's rounded rect. */
.promo-plain-shine {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
    pointer-events: none;
    z-index: 2;
}

.promo-plain-shine::after {
    content: "";
    position: absolute;
    inset: -40%;
    background: radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, .5), transparent 42%);
    opacity: var(--glow);
    transition: opacity .35s ease;
}

/* Corner foil seal, same conic-gradient iridescent trick as the
   coupon hologram, retuned to teal/sapphire/gold. */
.promo-plain-seal {
    position: absolute;
    top: 16px;
    right: 18px;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: conic-gradient(from 200deg, #5fd9d3, #eaf6ff, #e3ac4e, #5fd9d3, #1d4ed8, #5fd9d3);
    mix-blend-mode: soft-light;
    opacity: .75;
    z-index: 1;
    pointer-events: none;
}

.promo-plain-seal svg {
    width: 100%;
    height: 100%;
    color: rgba(6, 11, 24, .55);
}

/* Faded brand watermark bled off the corner, same CSS-mask technique
   as the coupon card's cardmark — recolored to the card's own cool
   palette. Sits below the text content (z-index 1 vs 3). */
.promo-plain-mark {
    position: absolute;
    right: -20px;
    bottom: -20px;
    width: 118px;
    height: 118px;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(155deg, var(--foil-4) 0%, #eaf6ff 35%, var(--foil-3) 55%, var(--foil-2) 100%);
    -webkit-mask-image: url('vikalink-icon.png');
    mask-image: url('vikalink-icon.png');
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    opacity: .18;
    mix-blend-mode: overlay;
}

html[data-theme="dark"] .promo-plain-mark {
    opacity: .22;
    mix-blend-mode: soft-light;
}

.promo-plain-card > .announcement-head,
.promo-plain-card > .announcement-body {
    position: relative;
    z-index: 3;
}

.promo-plain-card .announcement-title {
    color: #f3faff;
    text-shadow: 0 1px 2px rgba(3, 8, 20, .4);
}

.promo-plain-card .announcement-body {
    color: rgba(234, 246, 255, .8);
}

.promo-plain-card .announcement-pin-badge {
    color: #2c1e0b;
    background: linear-gradient(135deg, #f6e4ac, #e3ac4e);
    border-color: rgba(227, 172, 78, .6);
}

/* Discount/callout pill on a plain foil promo card — enlarged and
   given a stronger glow + highlight ring so it reads as a real
   "offer" tag against the busy foil background, same intent as the
   hero version's gold treatment above (kept in this card's own teal
   instead, to match its foil palette). */
.promo-plain-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #062026;
    background: linear-gradient(135deg, #9be9e4, #29c7c1);
    border: 1px solid rgba(255, 255, 255, .5);
    border-radius: 20px;
    padding: 6px 14px;
    white-space: nowrap;
    box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 4px 12px -3px rgba(41, 199, 193, .55);
}

.promo-plain-badge svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

@media (max-width: 720px) {
    .promo-hero-banner {
        flex-direction: column;
        padding: 24px;
        gap: 20px;
    }

    .promo-hero-media {
        flex-basis: auto;
    }

    .promo-hero-media img {
        min-height: 180px;
    }
}

@media (max-width: 640px) {
    .promo-plain-card {
        padding: 16px 18px;
    }
}


/* ---------- Payment Methods ---------- */

.paymethod-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 20px;
}

.paymethod-card {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 20px 20px 18px;
    box-shadow: var(--shadow);
}

.paymethod-card.is-default {
    border-color: var(--primary);
}

.paymethod-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
}

.paymethod-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    background: var(--primary-tint);
    color: var(--primary);
}

.paymethod-icon svg {
    width: 19px;
    height: 19px;
}

.paymethod-default-badge {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--success);
    background: var(--success-tint);
    border: 1px solid rgba(30, 142, 90, 0.25);
    border-radius: 20px;
    padding: 3px 10px;
}

.paymethod-title {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.paymethod-meta {
    margin: 0 0 16px;
    font-size: 12.5px;
    color: var(--muted);
}

.paymethod-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: auto;
    padding-top: 12px;
    border-top: 1px solid var(--line);
}

.paymethod-actions form {
    display: contents;
}

.paymethod-action-btn {
    appearance: none;
    border: 1px solid var(--line);
    background: var(--surface);
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    padding: 7px 12px;
    border-radius: 8px;
    color: var(--ink);
    transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
}

.paymethod-action-btn.is-primary {
    color: var(--primary);
}

.paymethod-action-btn.is-primary:hover {
    border-color: var(--primary);
    background: var(--primary-tint);
}

.paymethod-action-btn.is-danger {
    color: var(--muted);
    margin-left: auto;
}

.paymethod-action-btn.is-danger:hover {
    border-color: var(--danger);
    background: var(--danger-tint);
    color: var(--danger);
}

/* ---------- Message detail ---------- */

.message-detail-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 28px;
    max-width: 720px;
    box-shadow: var(--shadow);
}

.message-detail-from {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 22px;
    margin-bottom: 22px;
    border-bottom: 1px solid var(--line);
}

.message-detail-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--primary-tint);
    color: var(--primary);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
}

.message-detail-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.message-detail-from-name {
    font-size: 14px;
    font-weight: 600;
}

.message-detail-from-meta {
    font-size: 12px;
    color: var(--muted);
}

.message-detail-body {
    font-size: 14.5px;
    line-height: 1.7;
    white-space: pre-wrap;
}

/* ---------- Footer ---------- */

.app-footer {
    flex-shrink: 0;
    padding: 18px 28px;
    border-top: 1px solid var(--line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12.5px;
    color: var(--muted);
}

.app-footer a {
    color: var(--muted);
    text-decoration: none;
    margin-left: 18px;
}

.app-footer a:hover {
    color: var(--primary);
}

.app-footer .footer-links a:first-child {
    margin-left: 0;
}

/* ---------- Order (configure/review) ---------- */

.order-card {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 0;
    max-width: 780px;
    margin: 0 auto;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: var(--shadow);
    overflow: hidden;
}

.order-summary {
    position: relative;
    background: var(--surface-raised);
    border-right: 1px solid var(--line);
    padding: 26px 22px;
}

.order-summary-name {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0 0 4px;
    padding-right: 20px;
}

.order-summary-tagline {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 18px;
}

.order-summary-desc {
    font-size: 13px;
    color: var(--muted);
    line-height: 1.5;
    margin: 0 0 18px;
}

.order-form {
    padding: 26px 26px 24px;
}

.order-step-title {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    margin: 0 0 4px;
}

.order-step-sub {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 20px;
}

.order-step.is-hidden {
    display: none;
}

.order-field {
    margin-bottom: 18px;
}

.order-field label {
    display: block;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    margin-bottom: 7px;
}

.order-field input {
    width: 100%;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-family: var(--font-body);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.order-field input::placeholder,
.order-field textarea::placeholder {
    color: #98A3B8;
}

.order-field input:focus,
.order-field select:focus,
.order-field textarea:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15);
}

.order-field select,
.order-field textarea {
    width: 100%;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-family: var(--font-body);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.order-field select {
    appearance: none;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2398A3B8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M5.5 8l4.5 4.5L14.5 8'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 34px;
    cursor: pointer;
}

.order-field textarea {
    resize: vertical;
    min-height: 90px;
    line-height: 1.55;
}

.order-field-hint {
    font-size: 12px;
    color: var(--muted);
    margin: 6px 0 0;
}

.order-field-error {
    display: none;
    font-size: 12.5px;
    color: var(--danger);
    margin: 6px 0 0;
}

.order-field.has-error input {
    border-color: var(--danger);
}

.order-field.has-error .order-field-error {
    display: block;
}

/* Order Configure step — "Register a new domain" / "I already own
   this domain" toggle (order.php). Built on top of the .order-field
   primitives above rather than the .domain-search-panel hero styling
   — this sits inside the light order-card, not a standalone page
   section. */
.order-domain-toggle {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 16px;
}

.order-domain-toggle-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.order-domain-toggle-option input {
    margin: 0;
    accent-color: var(--primary);
    flex-shrink: 0;
}

.order-domain-toggle-option:has(input:checked) {
    border-color: var(--primary);
    color: var(--ink);
    background: var(--accent-tint);
}

.order-domain-panel {
    margin-bottom: 6px;
}

.order-domain-search-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.order-domain-search-row input {
    flex: 1;
    min-width: 0;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-family: var(--font-body);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.order-domain-search-row input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15);
}

.order-domain-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.order-domain-chip {
    font-family: var(--font-mono);
    font-size: 11.5px;
    letter-spacing: 0.02em;
    color: var(--muted);
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 20px;
    padding: 4px 11px;
    cursor: pointer;
    transition: border-color 0.12s ease, color 0.12s ease;
}

.order-domain-chip:hover {
    border-color: var(--primary);
    color: var(--primary);
}

.order-domain-search-status {
    font-size: 12.5px;
    color: var(--muted);
    margin-top: 10px;
}

.order-domain-search-status.is-error {
    color: var(--danger);
}

.order-domain-results {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 12px;
    max-height: 260px;
    overflow-y: auto;
}

.order-domain-result-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 12px;
}

.order-domain-result-main {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.order-domain-result-name-row {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
}

.order-domain-result-name {
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 600;
    word-break: break-all;
}

.order-domain-result-price {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--muted);
}

.order-domain-result-row .order-btn-primary,
.order-domain-result-row .order-btn-secondary {
    padding: 7px 14px;
    font-size: 12.5px;
    flex-shrink: 0;
}

.order-domain-selected {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--accent-tint);
    border: 1px solid rgba(29, 78, 216, 0.25);
    border-radius: 8px;
    padding: 12px 14px;
    margin-top: 12px;
}

.order-domain-selected-info {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.order-domain-selected-name {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    word-break: break-all;
}

.order-domain-selected-price {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--muted);
}

.order-domain-selected-change {
    background: none;
    border: none;
    color: var(--primary);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 6px;
    flex-shrink: 0;
}

.order-domain-selected-change:hover {
    text-decoration: underline;
}

@media (max-width: 640px) {
    .order-domain-toggle {
        grid-template-columns: 1fr;
    }

    .order-domain-result-row {
        flex-wrap: wrap;
    }
}

.order-review-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 11px 0;
    border-bottom: 1px solid var(--line);
    font-size: 14px;
}

.order-review-row span:first-child {
    color: var(--muted);
}

.order-review-row span:last-child {
    font-weight: 500;
    text-align: right;
}

.order-review-total {
    border-bottom: none;
    padding-top: 14px;
}

.order-review-total span:first-child {
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--ink);
}

.order-review-total span:last-child {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 700;
}

.order-coupon-row {
    margin: 4px 0 18px;
}

.order-coupon-row label {
    display: block;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    margin-bottom: 7px;
}

.order-coupon-input-group {
    display: flex;
    gap: 8px;
}

.order-coupon-input-group input {
    flex: 1;
    min-width: 0;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-family: var(--font-body);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.order-coupon-input-group input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.15);
}

.order-coupon-input-group .order-btn-secondary {
    flex-shrink: 0;
}

.order-coupon-status {
    font-size: 12.5px;
    color: var(--success);
    margin: 8px 0 0;
}

.order-coupon-status.is-error {
    color: var(--danger);
}

.order-review-discount span:first-child,
.order-review-discount span:last-child {
    color: var(--success);
}

.order-review-discount.is-hidden {
    display: none;
}

.order-review-note {
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.5;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 12px;
    margin: 16px 0 0;
}

.order-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 22px;
}

/* Matches .store-order-btn (the hosting-plan CTA) so every primary
   action button in the client area shares one look, including the
   text-decoration reset needed since this class is also put on <a>
   tags (order-confirmation.php, cart.php, provisioning.php, etc.). */
.order-btn-primary {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: #fff;
    background: var(--primary);
    border: 1px solid var(--primary);
    border-radius: 10px;
    padding: 11px 18px;
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 6px 14px -6px rgba(29, 78, 216, .55);
    transition: filter 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.order-btn-primary:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
    box-shadow: 0 10px 20px -8px rgba(29, 78, 216, .6);
}

.order-btn-primary:active {
    transform: translateY(0);
    box-shadow: 0 4px 10px -6px rgba(29, 78, 216, .5);
}

.order-btn-primary:disabled,
.order-btn-primary[aria-disabled="true"] {
    background: var(--surface-raised);
    border-color: var(--line);
    color: var(--muted);
    box-shadow: none;
    cursor: not-allowed;
}

/* Danger variant — same flat-fill shape as the default .order-btn-primary
   above, just swapped to --danger, for destructive confirms like the
   Request Cancellation modal's submit button (services.php). */
.order-btn-primary.is-danger {
    background: var(--danger);
    border-color: var(--danger);
    box-shadow: 0 6px 14px -6px rgba(192, 57, 43, .45);
}

.order-btn-primary.is-danger:hover {
    box-shadow: 0 10px 20px -8px rgba(192, 57, 43, .5);
}

.order-btn-primary.is-danger:active {
    box-shadow: 0 4px 10px -6px rgba(192, 57, 43, .4);
}

.order-btn-primary.is-danger:disabled,
.order-btn-primary.is-danger[aria-disabled="true"] {
    background: var(--surface-raised);
    border-color: var(--line);
    color: var(--muted);
    box-shadow: none;
}

.order-btn-secondary {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 500;
    color: var(--ink);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 16px;
    cursor: pointer;
    transition: border-color 0.12s ease;
}

.order-btn-secondary:hover {
    border-color: var(--primary);
}

@media (max-width: 640px) {
    .order-card {
        grid-template-columns: 1fr;
    }

    .order-summary {
        border-right: none;
        border-bottom: 1px solid var(--line);
    }

    /* Same class of bug as the invoice detail header above: two
       buttons side by side with no wrap and no shrink allowance can
       run past the edge of a narrow phone screen once their labels
       ("Continue to review", "Place Order") are accounted for.
       Stacking them at a guaranteed 100% width (primary action on top,
       since that's the one most clients want) removes the overflow
       risk the same way. */
    .order-actions {
        flex-direction: column-reverse;
        align-items: stretch;
    }

    .order-actions .order-btn-primary,
    .order-actions .order-btn-secondary {
        width: 100%;
        justify-content: center;
    }
}

/* ---------- Store ---------- */

.store-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 24px;
}

.store-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.store-tab {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 100px;
    padding: 7px 14px;
    cursor: pointer;
    transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}

.store-tab:hover {
    color: var(--ink);
    border-color: var(--primary);
}

.store-tab.is-active {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

.store-sort-select {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 100px;
    padding: 8px 16px;
    cursor: pointer;
    flex-shrink: 0;
}

.store-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
    gap: 26px;
    align-items: stretch;
}

.store-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    padding: 30px 26px 26px;
    box-shadow: var(--shadow);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

.store-card:hover {
    transform: translateY(-5px);
    box-shadow: var(--shadow-tile-hover);
}

.store-card.is-hidden {
    display: none;
}

/* Featured plan reads as the "recommended" pick via a colored border,
   a stronger tinted shadow, and a soft gradient wash behind its
   header — rather than the old flat 4px top bar — without scaling the
   card itself (which would need it to overlap its grid neighbours to
   read as bigger, and that's fragile at narrow widths). */
.store-card.is-featured {
    border-color: var(--primary);
    box-shadow: 0 1px 2px rgba(11, 27, 59, .06), 0 20px 40px -18px rgba(29, 78, 216, .45);
}

.store-card.is-featured:hover {
    transform: translateY(-7px);
    box-shadow: 0 1px 2px rgba(11, 27, 59, .06), 0 26px 48px -18px rgba(29, 78, 216, .5);
}

.store-card.is-featured::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 136px;
    /* Rounded to match .store-card's own corners: with `overflow`
       removed from .store-card (needed so the "Most Popular" pill
       below can float above the card's top edge instead of being
       clipped), this wash needs its own matching top radius rather
       than relying on the parent to crop its square corners. */
    border-radius: 18px 18px 0 0;
    background: linear-gradient(180deg, var(--primary-tint) 0%, rgba(29, 78, 216, 0) 100%);
    pointer-events: none;
}

/* Keeps every real card child above the featured gradient wash, which
   is itself the first (and otherwise topmost-painted) child. */
.store-card > * {
    position: relative;
}

/* Product photo (products.imageUrl, set from the admin Products form)
   — bleeds out to the card's own edges/corners via negative margins
   matching .store-card's padding, so it reads as a photo header
   rather than an inset thumbnail. Sits below .store-badge-ribbon
   (z-index 2, unaffected here) and above .store-card.is-featured's
   gradient wash, same stacking .store-card > * already gives every
   direct child. */
.store-card-photo {
    margin: -30px -26px 18px;
    border-radius: 18px 18px 0 0;
    overflow: hidden;
    background: var(--surface-raised);
}

.store-card-photo img {
    display: block;
    width: 100%;
    height: 140px;
    object-fit: cover;
}

/* "Most Popular" pill — floats centered over the card's top edge, the
   way Stripe/Vercel-style pricing tables call out a recommended plan,
   in place of the old diagonal corner-sticker ribbon. */
.store-badge-ribbon {
    position: absolute;
    top: -13px;
    left: 50%;
    transform: translateX(-50%);
    display: inline-flex;
    align-items: center;
    gap: 5px;
    width: max-content;
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #fff;
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-shade) 100%);
    padding: 6px 16px;
    border-radius: 100px;
    box-shadow: 0 4px 10px -2px rgba(29, 78, 216, .5), 0 0 0 3px var(--surface);
    z-index: 2;
}

.store-badge-ribbon::before {
    content: "\2605";
    font-size: 9px;
    line-height: 1;
}

.store-card-name {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 6px 0 4px;
}

.store-card-tagline {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 20px;
}

.store-price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin-bottom: 6px;
}

.store-price-amount {
    font-family: var(--font-display);
    font-size: 32px;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--ink);
}

.store-price-suffix {
    font-size: 13px;
    font-weight: 600;
    color: var(--muted);
}

.store-price-note {
    font-size: 12px;
    color: var(--muted);
    margin: 0 0 20px;
}

.store-card-desc {
    font-size: 13.5px;
    color: var(--muted);
    line-height: 1.55;
    margin: 0 0 20px;
    padding-bottom: 20px;
    border-bottom: 1px solid var(--line);
}

.store-features {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 0 0 24px;
    padding: 0;
    flex: 1;
}

.store-features li {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13.5px;
    color: var(--ink);
    line-height: 1.4;
}

/* Checkmark sits inside a small tinted circular badge rather than a
   bare stroke icon, so it reads as a deliberate "included" marker —
   the same treatment premium SaaS pricing tables use — instead of a
   leftover to-do checkbox glyph. */
.store-features svg {
    width: 12px;
    height: 12px;
    padding: 4px;
    box-sizing: content-box;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--success-tint);
    color: var(--success);
}

.store-card-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: auto;
    padding-top: 20px;
}

.store-order-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: #fff;
    background: var(--primary);
    border: 1px solid var(--primary);
    border-radius: 10px;
    padding: 11px 14px;
    cursor: pointer;
    text-decoration: none;
    box-shadow: 0 6px 14px -6px rgba(29, 78, 216, .55);
    transition: filter 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.store-order-btn:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
    box-shadow: 0 10px 20px -8px rgba(29, 78, 216, .6);
}

.store-order-btn:active {
    transform: translateY(0);
    box-shadow: 0 4px 10px -6px rgba(29, 78, 216, .5);
}

.store-order-btn:disabled,
.store-order-btn[aria-disabled="true"] {
    background: var(--surface-raised);
    border-color: var(--line);
    color: var(--muted);
    box-shadow: none;
    cursor: not-allowed;
}

.store-cart-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 11px 14px;
    cursor: pointer;
    transition: filter 0.12s ease, background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.store-cart-btn:hover {
    background: var(--surface-raised);
    border-color: var(--primary);
    transform: translateY(-1px);
}

.store-cart-btn:disabled {
    cursor: not-allowed;
    opacity: 0.7;
    transform: none;
}

.store-cart-btn.is-done {
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
    color: var(--success);
}

/* Servers store's Custom-term picker (store-servers.php) — a small
   Monthly/Custom radio toggle sitting above the Configure button,
   only rendered for plans that have a priceMonthly to derive a
   custom term's total from (see that card's own PHP comment). */
.server-cycle-picker {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.server-cycle-options {
    display: flex;
    gap: 6px;
}

.server-cycle-option {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 7px 8px;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.server-cycle-option:has(.server-cycle-radio:checked) {
    color: var(--primary);
    border-color: var(--primary);
    background: var(--surface-raised);
}

.server-cycle-option .server-cycle-radio {
    margin: 0;
    accent-color: var(--primary);
}

.server-cycle-custom-field {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.server-cycle-custom-field.is-hidden {
    display: none;
}

.server-cycle-months-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 12.5px;
    color: var(--muted);
}

.server-cycle-months-input {
    width: 64px;
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 6px 8px;
}

.server-cycle-custom-total {
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 600;
    color: var(--ink);
    text-align: right;
    flex: 1;
}

/* Servers store's OS dropdown (store-servers.php) — sits above the
   Custom-term picker/Configure button, same card-actions column, same
   visual weight as the cycle picker just above so the two read as one
   "configure before adding" group. */
.server-os-picker {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.server-os-picker-label {
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--muted);
}

.server-os-select {
    width: 100%;
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 7px 8px;
    cursor: pointer;
}

.server-os-select:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

.store-group-heading {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    color: var(--ink);
    margin: 28px 0 14px;
}

.store-group-heading:first-child {
    margin-top: 0;
}

/* Cross-sell "Recommended add-ons" panel — billing_data.php's
   cross_sell_addons_for_group(), shown below a Store category's own
   grid (currently store-servers.php). Deliberately lighter-weight
   than .store-card (no chassis/feature list — an add-on is a small
   nudge alongside the main plans, not another full pricing tile). */
.cross-sell-section {
    margin-top: 36px;
    padding-top: 28px;
    border-top: 1px solid var(--line);
}

.cross-sell-heading {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--ink);
    margin: 0 0 4px;
}

.cross-sell-subheading {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 18px;
}

.cross-sell-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 16px;
}

.cross-sell-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 14px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 14px;
    padding: 18px 18px 16px;
    transition: border-color .15s ease, transform .15s ease;
}

.cross-sell-card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
}

.cross-sell-card-name {
    font-family: var(--font-display);
    font-size: 14.5px;
    font-weight: 700;
    color: var(--ink);
    margin: 0 0 4px;
}

.cross-sell-card-tagline {
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.5;
    margin: 0;
}

.cross-sell-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.cross-sell-price {
    display: flex;
    align-items: baseline;
    gap: 3px;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    white-space: nowrap;
}

.cross-sell-price-suffix {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--muted);
}

.cross-sell-add-btn {
    width: auto;
    flex: 0 0 auto;
    padding: 8px 14px;
    font-size: 12.5px;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .store-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .store-grid {
        grid-template-columns: 1fr;
    }

    .cross-sell-grid {
        grid-template-columns: 1fr;
    }

    .cross-sell-card {
        flex-direction: column;
        align-items: stretch;
    }

    .cross-sell-card-footer {
        flex-wrap: wrap;
    }
}

/* ---------- Sidebar backdrop (mobile) ---------- */

.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(11, 27, 59, 0.45);
    z-index: 25;
}

/* ---------- Mobile ---------- */

@media (max-width: 900px) {
    .sidebar {
        transform: translateX(-100%);
    }

    .app-shell.sidebar-open .sidebar {
        transform: translateX(0);
    }

    .app-shell.sidebar-open .sidebar-backdrop {
        display: block;
    }

    .main-column {
        margin-left: 0;
    }

    .sidebar-toggle {
        display: inline-flex;
    }

    .topbar {
        padding: 0 16px;
    }

    .content {
        padding: 22px 16px 32px;
    }

    /* Sidebar becomes a full off-canvas drawer at this breakpoint (see
       .sidebar above), so it's read and tapped one-handed on a phone —
       bump text and tap-target size a bit further than the desktop
       sizing above for that context. */
    .nav-link,
    .nav-group-head {
        padding: 13px 12px;
        font-size: 19px;
    }

    .nav-group-link {
        padding: 11px 12px 11px 34px;
        font-size: 18px;
    }

    .app-footer {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        padding: 16px;
    }

    .footer-links a:first-child {
        margin-left: 0;
    }

    .topbar-user {
        padding-left: 10px;
        gap: 10px;
    }
}

@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
    }
}

/* ---------- Domains list ---------- */

.domain-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.domain-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.domain-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

.domain-row-start {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    min-width: 0;
    flex: 1;
}

/* Select-all control above the list + per-row checkboxes — a shared
   custom checkbox (input hidden, styled box + checkmark drawn with a
   pseudo-element) that also backs the bulk actions bar below. */
.domain-list-controls {
    display: flex;
    margin-bottom: 2px;
}

.domain-select,
.domain-select-all {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    cursor: pointer;
    user-select: none;
}

.domain-select-all {
    font-size: 12.5px;
    color: var(--muted);
    font-weight: 500;
}

.domain-select {
    flex-shrink: 0;
    margin-top: 2px;
}

.domain-select input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.domain-select-box {
    position: relative;
    width: 19px;
    height: 19px;
    flex-shrink: 0;
    border-radius: 6px;
    border: 1.5px solid var(--line);
    background: var(--surface);
    transition: background-color .12s ease, border-color .12s ease;
}

.domain-select-box::after {
    content: "";
    position: absolute;
    left: 6px;
    top: 2px;
    width: 5px;
    height: 10px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(40deg);
    opacity: 0;
}

.domain-select input:checked + .domain-select-box,
.domain-select-all input:checked + .domain-select-box {
    background: var(--primary);
    border-color: var(--primary);
}

.domain-select input:checked + .domain-select-box::after,
.domain-select-all input:checked + .domain-select-box::after {
    opacity: 1;
}

.domain-select-all input:indeterminate + .domain-select-box {
    background: var(--primary);
    border-color: var(--primary);
}

.domain-select-all input:indeterminate + .domain-select-box::after {
    opacity: 1;
    top: 8px;
    left: 4px;
    width: 9px;
    height: 2px;
    border-width: 2px 0 0 0;
    transform: none;
}

.domain-select input:focus-visible + .domain-select-box,
.domain-select-all input:focus-visible + .domain-select-box {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.domain-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.domain-name-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.domain-name {
    font-family: var(--font-display);
    font-size: 15.5px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.domain-autorenew {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
}

.domain-since {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.domain-expiry {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.domain-expiry.is-soon {
    color: var(--warning);
}

.domain-expiry.is-expired {
    color: var(--danger);
}

.domain-nameservers {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.domain-billing-cycle {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.domain-ns-pending {
    display: inline-flex;
    align-self: flex-start;
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--info);
    background: var(--info-tint);
    border: 1px solid rgba(58, 110, 165, 0.25);
    border-radius: 20px;
    padding: 2px 9px;
}

.domain-side {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    flex-shrink: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.domain-price-group {
    display: flex;
    align-items: baseline;
    gap: 14px;
    flex-shrink: 0;
    padding-top: 2px;
}

.domain-price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    flex-shrink: 0;
    white-space: nowrap;
}

/* Domain management menu — a single "Manage" button per active
   domain that opens a dropdown of actions (EPP/Auth Code, Nameservers,
   Auto-Renew, WHOIS Privacy, Domain Lock), replacing what used to be
   a row of standalone buttons. Modelled on the notification bell's
   toggle+panel pattern above (.notif-toggle/.notif-panel) so it opens
   the same way and gets the same elevated-panel treatment. */
.domain-manage {
    position: relative;
    flex-shrink: 0;
    align-self: flex-start;
}

.domain-manage-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    padding: 0 14px 0 12px;
    border-radius: 10px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    box-shadow: var(--shadow-tile);
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.domain-manage-toggle svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--primary);
}

.domain-manage-toggle:hover,
.domain-manage-toggle[aria-expanded="true"] {
    border-color: var(--primary);
    box-shadow: var(--shadow-tile-hover);
    transform: translateY(-1px);
}

.domain-manage-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 288px;
    max-width: calc(100vw - 32px);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: var(--shadow-elevated);
    padding: 8px;
    z-index: 30;
}

.domain-manage-panel-head {
    padding: 6px 8px 8px;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
}

.domain-manage-item-row + .domain-manage-item-row,
.domain-manage-divider + .domain-manage-item-row,
.domain-manage-item-row + .domain-manage-toggle-item,
.domain-manage-toggle-item + .domain-manage-item-row {
    margin-top: 1px;
}

.domain-manage-item,
.domain-manage-toggle-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px;
    border: none;
    border-radius: 9px;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease;
}

.domain-manage-toggle-item {
    cursor: default;
    user-select: none;
}

.domain-manage-item:hover:not(:disabled),
.domain-manage-toggle-item:hover {
    background: var(--surface-raised);
}

.domain-manage-item:disabled {
    cursor: default;
    opacity: 0.7;
}

.domain-manage-item-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--primary-tint);
    color: var(--primary);
}

.domain-manage-item-icon svg {
    width: 14px;
    height: 14px;
}

.domain-manage-item-icon.is-ns { background: var(--info-tint); color: var(--info); }
.domain-manage-item-icon.is-renew { background: var(--success-tint); color: var(--success); }
.domain-manage-item-icon.is-whois { background: var(--info-tint); color: var(--info); }
.domain-manage-item-icon.is-lock { background: var(--warning-tint); color: var(--warning); }
/* Server management dropdown (services.php, Servers-group services) —
   same icon-color convention as the domain ones just above. */
.domain-manage-item-icon.is-power-on { background: var(--success-tint); color: var(--success); }
.domain-manage-item-icon.is-power-off { background: var(--danger-tint); color: var(--danger); }
.domain-manage-item-icon.is-reboot { background: var(--info-tint); color: var(--info); }
.domain-manage-item-icon.is-reinstall { background: var(--danger-tint); color: var(--danger); }
.domain-manage-item-icon.is-reset-password { background: var(--warning-tint); color: var(--warning); }
.domain-manage-item-icon.is-cancel { background: var(--danger-tint); color: var(--danger); }

.domain-manage-item-label {
    flex: 1;
    min-width: 0;
}

.domain-manage-item-chevron {
    flex-shrink: 0;
    width: 13px;
    height: 13px;
    color: var(--muted);
}

.domain-manage-item.is-done,
.domain-manage-item.is-pending {
    background: var(--success-tint);
}

.domain-manage-item.is-done .domain-manage-item-icon,
.domain-manage-item.is-pending .domain-manage-item-icon {
    background: var(--surface);
}

.domain-manage-item.is-pending {
    background: var(--info-tint);
}

.domain-manage-item-sub {
    display: block;
    padding: 0 8px 8px 46px;
    margin-top: -2px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--muted);
}

.domain-manage-item-sub.is-error {
    color: var(--danger);
}

.domain-manage-divider {
    height: 1px;
    margin: 6px 4px;
    background: var(--line);
}

/* Auto-Renew lives in the menu as a labelled row with the toggle
   switch pinned to the right, reusing the same track/knob visuals
   the old standalone toggle used. */
.domain-config-toggle-inline {
    position: relative;
    flex-shrink: 0;
    margin-left: auto;
}

.domain-config-toggle-inline input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.domain-config-toggle-track {
    position: relative;
    display: block;
    width: 34px;
    height: 19px;
    flex-shrink: 0;
    border-radius: 20px;
    background: var(--line);
    transition: background 0.15s ease;
}

.domain-config-toggle-track::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 2px rgba(11, 27, 59, .25);
    transition: transform 0.15s ease;
}

.domain-config-toggle-inline input:checked + .domain-config-toggle-track {
    background: var(--primary);
}

.domain-config-toggle-inline input:checked + .domain-config-toggle-track::before {
    transform: translateX(15px);
}

.domain-config-toggle-inline input:disabled + .domain-config-toggle-track {
    opacity: 0.5;
}

.domain-config-note {
    max-width: 260px;
    margin: 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--muted);
    text-align: right;
}

.domain-price-value {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 600;
}

.domain-price-suffix {
    font-size: 12px;
    color: var(--muted);
}

.domain-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: capitalize;
    letter-spacing: 0.04em;
    padding: 2px 9px;
    border-radius: 20px;
    border: 1px solid transparent;
}

.domain-pill.status-active {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.domain-pill.status-pending {
    color: var(--info);
    background: var(--info-tint);
    border-color: rgba(58, 110, 165, 0.25);
}

.domain-pill.status-expired {
    color: var(--danger);
    background: var(--danger-tint);
    border-color: rgba(192, 57, 43, 0.25);
}

/* SSL Status pill — admin-set (office's Edit Domain form), shown
   read-only on active domains only (see domains.php). Green/"Active"
   reuses .domain-pill.status-active's palette; "Inactive" is neutral
   grey rather than red/danger, since an SSL cert simply not being
   configured yet isn't inherently an error state the way an expired
   domain is — same reasoning .service-pill.status-cancelled is grey
   rather than red. */
.domain-ssl-pill.is-ssl-active {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.domain-ssl-pill.is-ssl-inactive {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
    opacity: 0.75;
}

/* Padlock glyph inside the pill above — fill: currentColor means it
   automatically picks up whichever of the two colors just above
   applies (green for active, faint grey for inactive) with no extra
   variants of the icon needed. */
.domain-ssl-icon {
    width: 9px;
    height: 9px;
    fill: currentColor;
    vertical-align: -1px;
    margin-right: 3px;
    flex-shrink: 0;
}

/* Bulk actions bar — appears below the domain list once at least one
   row checkbox is checked (domains.php + footer.php's bulk selection
   block). Sticky to the bottom of the scrolling content area so it
   stays reachable with a long list, same "surface card, elevated
   shadow" treatment as .domain-row itself. */
.bulk-actions-bar {
    position: sticky;
    bottom: 16px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px 24px;
    margin-top: 12px;
    padding: 14px 18px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: var(--shadow-elevated);
    z-index: 10;
}

/* .bulk-actions-bar's own `display: flex` above has the same
   specificity as the browser's default `[hidden] { display: none }`
   rule, and author styles beat UA styles on a tie — so without this,
   the bar ignored its `hidden` attribute and showed at 0 selected on
   every page load. */
.bulk-actions-bar[hidden] {
    display: none;
}

.bulk-actions-count {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
    font-size: 13px;
    color: var(--muted);
}

.bulk-actions-count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    height: 24px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--primary);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 700;
}

.bulk-actions-list {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 20px;
    flex: 1;
}

.bulk-action-wrap {
    position: relative;
}

.bulk-action-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--primary);
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.bulk-action-btn svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.bulk-action-btn:hover,
.bulk-action-btn[aria-expanded="true"] {
    text-decoration: underline;
}

.bulk-action-menu {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    width: 190px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: var(--shadow-elevated);
    padding: 6px;
    z-index: 30;
}

.bulk-action-menu-item {
    display: block;
    width: 100%;
    padding: 8px 9px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease;
}

.bulk-action-menu-item:hover {
    background: var(--surface-raised);
}

.bulk-action-menu-item + .bulk-action-menu-item {
    margin-top: 1px;
}

.bulk-actions-status {
    flex-basis: 100%;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--muted);
}

.bulk-actions-status.is-error {
    color: var(--danger);
}

@media (max-width: 640px) {
    .bulk-actions-bar {
        bottom: 8px;
        flex-direction: column;
        align-items: stretch;
    }

    .bulk-action-menu {
        left: 0;
        transform: none;
    }
}

@media (max-width: 640px) {
    .domain-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .domain-side {
        align-self: stretch;
        /* Was space-between, left over from when this row also held a
           price display next to .domain-manage (see .domain-price-group
           above) — pricing moved inside the Manage dropdown's own "View
           Renewal Price" item, so .domain-side only ever has ONE child
           now (.domain-manage, or .domain-config-note on an expired
           domain). space-between with a single flex item packs it at
           flex-start instead of flex-end, which shoved the Manage
           button (and, since its dropdown panel is positioned relative
           to it, the panel too) over to the left edge of the screen —
           clipping most of the panel off-screen. flex-end keeps it
           pinned to the right, matching the desktop default above. */
        justify-content: flex-end;
    }

    .domain-manage-panel {
        right: 0;
        left: auto;
    }

    .domain-config-note {
        text-align: right;
        max-width: none;
    }
}

.domain-page-welcome {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

/* ---------- Inline domain search (top of Store / Domains) ---------- */
/* Replaces the old js-open-domain-search modal — this widget now
   sits directly in the page, hero-style, instead of behind a button. */

body.no-scroll {
    overflow: hidden;
}

.domain-search-panel {
    position: relative;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 18px;
    box-shadow: var(--shadow-elevated);
    padding: 34px 34px 30px;
    margin: 0 0 28px;
    overflow: hidden;
}

/* Faint one-tone corner glow — reads as texture, not a second color;
   the panel itself stays a flat, solid off-white (var(--surface-raised),
   a shade off pure white so the white search input/result rows inside
   it still read as their own layer) for a clean, professional look
   instead of the old two-tone gradient — or the flat navy this used to
   be before the portal-wide "no dark shades" pass (see this file's own
   top comment). */
.domain-search-panel::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(560px 280px at 100% 0%, var(--primary-tint), transparent 70%);
    pointer-events: none;
}

.domain-search-panel-eyebrow {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-tint);
    border: 1px solid rgba(14, 165, 165, 0.25);
    border-radius: 20px;
    padding: 5px 12px 5px 10px;
    margin-bottom: 16px;
}

.domain-search-panel-eyebrow svg {
    width: 14px;
    height: 14px;
}

.domain-search-panel-head {
    position: relative;
}

.domain-search-panel-head h2 {
    font-family: var(--font-display);
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--sidebar-text);
    margin: 0 0 6px;
}

.domain-search-panel-head p {
    color: var(--sidebar-muted);
    font-size: 13.5px;
    margin: 0 0 22px;
}

.domain-search-form {
    position: relative;
    margin-bottom: 4px;
}

.domain-search-input-row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: 12px;
    padding: 7px 7px 7px 16px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.06), 0 10px 24px -10px rgba(0, 0, 0, 0.45);
}

.domain-search-input-row:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(14, 165, 165, 0.22), 0 10px 24px -10px rgba(0, 0, 0, 0.45);
}

.domain-search-input-icon {
    width: 16px;
    height: 16px;
    color: var(--primary);
    flex-shrink: 0;
}

.domain-search-input-row input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    font-family: var(--font-body);
    font-size: 15px;
    color: var(--primary);
    padding: 11px 0;
    outline: none;
}

.domain-search-input-row .order-btn-primary {
    background: var(--primary);
    border-color: var(--primary);
    padding: 11px 20px;
    border-radius: 8px;
}

.domain-search-input-row .order-btn-primary:hover {
    filter: brightness(1.06);
}

.domain-search-chips {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 16px;
}

.domain-search-chip {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    color: var(--muted);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 20px;
    padding: 5px 12px;
    cursor: pointer;
    transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}

.domain-search-chip:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-tint);
}

.domain-search-status {
    position: relative;
    margin-top: 16px;
    font-size: 13px;
    color: var(--sidebar-muted);
}

.domain-search-status.is-error {
    color: var(--danger);
}

.domain-search-results {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 16px;
    max-height: 44vh;
    overflow-y: auto;
}

.domain-search-result-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: 10px;
    padding: 13px 15px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05), 0 6px 16px -8px rgba(0, 0, 0, 0.4);
}

.domain-search-result-main {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.domain-search-result-name-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.domain-search-result-name {
    font-family: var(--font-display);
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -0.01em;
    word-break: break-all;
}

.domain-search-result-badge {
    font-family: var(--font-mono);
    font-size: 9.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent);
    background: var(--accent-tint);
    border-radius: 20px;
    padding: 2px 8px;
}

.domain-search-result-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.04em;
    padding: 2px 9px;
    border-radius: 20px;
    border: 1px solid transparent;
}

.domain-search-result-pill.is-available {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.domain-search-result-pill.is-taken {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
}

.domain-search-result-price {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--muted);
}

.domain-search-result-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.domain-search-register-btn,
.domain-search-cart-btn {
    flex-shrink: 0;
    padding: 8px 16px;
    font-size: 13px;
    white-space: nowrap;
}

.domain-search-register-btn.is-done,
.domain-search-cart-btn.is-done {
    background: var(--success);
    border-color: var(--success);
    color: #fff;
}

/* ---------- Cart landing (cart.php) trust badges ---------- */
/* Sits between the page-welcome header and the domain-search-panel —
   same idea as the little feature checklist WHMCS's own cart.php
   shows above the domain configure box, built from
   .store-features' icon+text pairing but laid out in a row instead
   of a column since there are only four, short items here. */

.cart-trust-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 22px;
    margin: 0 0 22px;
}

.cart-trust-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--ink);
}

.cart-trust-item svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--success);
}

.domain-search-disclaimer {
    position: relative;
    margin: 18px 0 0;
    font-size: 11.5px;
    color: var(--sidebar-muted-dim);
    line-height: 1.5;
}

/* ---------- TLD pricing cards (domain-search.php) ---------- */
/* Small, clickable price cards sourced from domain_tld_pricing() —
   admin-editable via the billing app's Domain Pricing screen (see
   api/lib/domain_pricing.php's own top-of-file comment). Each card is
   a plain <button data-tld="..."> picked up by the same click handler
   as .domain-search-chip (see footer.php) — combines whatever's typed
   in the search box above with this TLD and runs a search, no extra
   click needed to "select" a TLD first. */

.domain-pricing-section {
    margin: 28px 0 0;
}

.domain-pricing-head {
    margin: 0 0 14px;
}

.domain-pricing-head h3 {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0 0 4px;
}

.domain-pricing-head p {
    color: var(--muted);
    font-size: 12.5px;
    margin: 0;
}

.domain-pricing-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: 14px;
    overflow: hidden;
    background: var(--surface);
}

.domain-pricing-list-head,
.domain-pricing-card {
    display: grid;
    grid-template-columns: 1.6fr 1fr 1fr 1fr;
    align-items: center;
    gap: 10px;
    padding: 13px 18px;
}

.domain-pricing-list-head {
    background: var(--surface-raised);
    border-bottom: 1px solid var(--line);
}

.dp-col-tld,
.dp-col {
    font-family: var(--font-body);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
}

.domain-pricing-list-head .dp-col-tld {
    text-align: left;
}

.domain-pricing-card {
    position: relative;
    width: 100%;
    background: var(--surface);
    border: none;
    border-bottom: 1px solid var(--line);
    text-align: left;
    cursor: pointer;
    font-family: var(--font-body);
    transition: background 0.12s ease;
}

.domain-pricing-card:last-child {
    border-bottom: none;
}

.domain-pricing-card:hover {
    background: var(--surface-raised);
}

.domain-pricing-card .dp-col-tld {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    text-transform: none;
    letter-spacing: normal;
}

.domain-pricing-card-tld {
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    white-space: nowrap;
    padding: 3px 11px;
    border-radius: 20px;
    /* background/color set per-TLD inline (see tld_chip_colors() in
       domain_pricing.php) so every TLD in the list gets its own
       distinct, bright, WCAG-contrast-checked color — these two rules
       are just a fallback for the rare case a TLD wasn't in the color
       map passed to this partial. */
    background: var(--accent-tint);
    color: var(--accent);
}

.domain-pricing-card-badge {
    font-family: var(--font-body);
    font-size: 10.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--accent);
    background: var(--accent-tint);
    border-radius: 20px;
    padding: 3px 9px;
    white-space: nowrap;
}

.domain-pricing-card .dp-value {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -0.02em;
    color: var(--ink);
    white-space: nowrap;
}

.domain-pricing-card .dp-value-new {
    color: var(--primary);
    font-weight: 400;
}

@media (max-width: 720px) {
    .domain-pricing-list-head {
        display: none;
    }

    .domain-pricing-card {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-areas:
            "tld  tld  tld"
            "new  renew transfer";
        row-gap: 10px;
        column-gap: 6px;
        padding: 16px;
    }

    .domain-pricing-card .dp-col-tld { grid-area: tld; }
    .domain-pricing-card .dp-value-new { grid-area: new; }
    .domain-pricing-card .dp-value-renewal { grid-area: renew; }
    .domain-pricing-card .dp-value-transfer { grid-area: transfer; }

    .domain-pricing-card-tld {
        font-size: 14px;
    }

    .domain-pricing-card-badge {
        display: inline-block;
    }

    .domain-pricing-card .dp-value {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 3px;
        font-size: 14px;
        min-width: 0;
    }

    /* Header row is hidden at this width, so each value gets its own
       inline label here instead — otherwise "GHS 205.45 / GHS 205.45"
       (renewal vs. transfer) would be unreadable without the column
       headings above them. */
    .domain-pricing-card .dp-value::before {
        font-family: var(--font-body);
        font-size: 10.5px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--muted);
    }

    .domain-pricing-card .dp-value-new::before { content: "New"; }
    .domain-pricing-card .dp-value-renewal::before { content: "Renewal"; }
    .domain-pricing-card .dp-value-transfer::before { content: "Transfer"; }
}

@media (max-width: 380px) {
    .domain-pricing-card .dp-value {
        font-size: 12.5px;
    }
}

@media (max-width: 640px) {
    .domain-search-panel {
        padding: 22px 18px 20px;
    }

    .domain-search-result-row {
        flex-direction: column;
        align-items: flex-start;
    }

    .domain-search-result-actions,
    .domain-search-result-row .order-btn-secondary {
        align-self: flex-end;
    }
}

/* ---------- Order success popup — colourful 3D pop-in modal ---------- */

.order-success-overlay {
    position: fixed;
    inset: 0;
    z-index: 999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(9, 14, 28, 0.55);
    backdrop-filter: blur(6px) saturate(1.1);
    -webkit-backdrop-filter: blur(6px) saturate(1.1);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s ease;
    perspective: 1200px;
}

.order-success-overlay.is-open {
    opacity: 1;
    visibility: visible;
}

/* Same off-canvas-sidebar offset as .pm-modal-overlay above: on desktop
   the fixed sidebar sits on top of this inset:0 overlay, so centering
   against the full viewport pulls the modal toward the sidebar instead
   of the visible content area. */
@media (min-width: 901px) {
    .order-success-overlay {
        left: var(--sidebar-width);
    }
}

.order-success-overlay.is-closing .order-success-modal {
    transform: scale(0.85) rotateX(8deg) translateY(10px);
    opacity: 0;
}

.order-success-modal {
    position: relative;
    width: 100%;
    max-width: 420px;
    padding: 38px 32px 30px;
    border-radius: 22px;
    text-align: center;
    color: #fff;
    background:
        radial-gradient(120% 140% at 15% -10%, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0) 55%),
        linear-gradient(150deg, #6D5BFF 0%, #8B5CF6 22%, #1D9BF0 55%, #0EA5A5 82%, #22C77A 100%);
    background-size: 220% 220%;
    box-shadow:
        0 2px 0 rgba(255, 255, 255, 0.35) inset,
        0 -30px 60px -25px rgba(0, 0, 0, 0.35) inset,
        0 30px 60px -18px rgba(29, 78, 216, 0.55),
        0 12px 30px -10px rgba(0, 0, 0, 0.4);
    transform: scale(0.7) rotateX(18deg) translateY(30px);
    opacity: 0;
    transform-style: preserve-3d;
    animation: order-success-shift 9s ease-in-out infinite;
    transition: transform 0.38s cubic-bezier(.2, 1.4, .4, 1), opacity 0.28s ease;
}

.order-success-overlay.is-open .order-success-modal {
    transform: scale(1) rotateX(0deg) translateY(0);
    opacity: 1;
}

@keyframes order-success-shift {
    0%, 100% { background-position: 0% 30%; }
    50% { background-position: 100% 70%; }
}

.order-success-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.order-success-close:hover {
    background: rgba(255, 255, 255, 0.32);
    transform: rotate(90deg);
}

.order-success-close svg {
    width: 13px;
    height: 13px;
}

.order-success-badge {
    width: 76px;
    height: 76px;
    margin: 0 auto 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(145deg, #FFFFFF, #E6FBF1);
    color: #1E8E5A;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.8) inset,
        0 14px 26px -10px rgba(0, 0, 0, 0.45),
        0 0 0 8px rgba(255, 255, 255, 0.16);
    animation: order-success-pop 0.55s cubic-bezier(.25, 1.6, .4, 1) 0.1s both;
}

@keyframes order-success-pop {
    0% { transform: scale(0) rotate(-30deg); }
    70% { transform: scale(1.12) rotate(4deg); }
    100% { transform: scale(1) rotate(0deg); }
}

.order-success-badge svg {
    width: 34px;
    height: 34px;
}

.order-success-badge-logo {
    width: 46px;
    height: 46px;
    object-fit: contain;
}

.order-success-title {
    margin: 0 0 10px;
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.01em;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.order-success-text {
    margin: 0 0 26px;
    font-size: 14.5px;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.94);
}

.order-success-text strong {
    font-family: var(--font-mono);
    font-weight: 500;
    background: rgba(255, 255, 255, 0.2);
    padding: 1px 7px;
    border-radius: 6px;
}

.order-success-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.order-success-pay {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 20px;
    border-radius: 12px;
    font-weight: 700;
    font-size: 14.5px;
    text-decoration: none;
    color: #14306B;
    background: linear-gradient(180deg, #FFFFFF, #E4ECFF);
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.9) inset,
        0 10px 20px -8px rgba(0, 0, 0, 0.45);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.order-success-pay:hover {
    transform: translateY(-2px);
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.9) inset,
        0 14px 24px -8px rgba(0, 0, 0, 0.5);
}

.order-success-pay:active {
    transform: translateY(0);
}

.order-success-dismiss {
    border: none;
    background: transparent;
    color: rgba(255, 255, 255, 0.78);
    font-size: 13px;
    font-weight: 500;
    padding: 4px;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.order-success-dismiss:hover {
    color: #fff;
}

/* store.php's order-success popup only: .price-card-btn is normally an
   inline chip-side button, but here it's the second half of a stacked
   full-width action pair with .order-success-pay, on a dark gradient
   modal rather than a white row. Centers its content and gives it a
   little more room so it reads as that button's equal-weight sibling
   rather than a shrunk-down chip action. */
.order-success-view-invoice {
    justify-content: center;
    padding: 10px 20px;
}

/* Domain-upsell popup only: "Add Hosting Plan" and "Checkout without
   hosting" are two equally real choices — WHMCS's own hosting-upsell
   pattern presents them the same way — not a primary action plus a
   throwaway dismiss link, so they sit side by side instead of the
   stacked Pay Invoice/View Invoice pair the order-confirmation popup
   uses. Scoped to this modifier class (added only on
   #domainUpsellOverlay's .order-success-actions in footer.php) so the
   store.php success popup's own stacked layout is untouched. */
.order-success-actions-row {
    flex-direction: row;
}

.order-success-actions-row > * {
    flex: 1;
}

/* A real secondary button, not a plain dismiss link — outlined against
   the modal's gradient rather than solid white, so it reads as a
   genuine alternative to "Add Hosting Plan" rather than a lesser
   "never mind" option. */
.order-success-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 18px;
    border-radius: 12px;
    font-weight: 700;
    font-size: 14.5px;
    text-decoration: none;
    color: #fff;
    background: rgba(255, 255, 255, 0.12);
    border: 1.5px solid rgba(255, 255, 255, 0.55);
    cursor: pointer;
    transition: transform 0.15s ease, background 0.15s ease;
}

.order-success-secondary:hover {
    background: rgba(255, 255, 255, 0.22);
    transform: translateY(-2px);
}

.order-success-secondary:active {
    transform: translateY(0);
}

@media (max-width: 480px) {
    .order-success-actions-row {
        flex-direction: column;
    }
}

/* Floating confetti dots drifting behind the modal */
.order-success-confetti {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.order-success-confetti span {
    position: absolute;
    top: -12px;
    width: 9px;
    height: 9px;
    border-radius: 3px;
    opacity: 0;
    animation: order-success-fall 3.6s ease-in infinite;
}

.order-success-overlay.is-open .order-success-confetti span {
    opacity: 1;
}

.order-success-confetti span:nth-child(1)  { left: 6%;  background: #FFD166; animation-delay: 0.05s; }
.order-success-confetti span:nth-child(2)  { left: 16%; background: #EF476F; animation-delay: 0.6s; border-radius: 50%; }
.order-success-confetti span:nth-child(3)  { left: 27%; background: #06D6A0; animation-delay: 0.2s; }
.order-success-confetti span:nth-child(4)  { left: 38%; background: #118AB2; animation-delay: 0.9s; border-radius: 50%; }
.order-success-confetti span:nth-child(5)  { left: 50%; background: #FFD166; animation-delay: 0.4s; }
.order-success-confetti span:nth-child(6)  { left: 61%; background: #8B5CF6; animation-delay: 1.1s; border-radius: 50%; }
.order-success-confetti span:nth-child(7)  { left: 72%; background: #EF476F; animation-delay: 0.15s; }
.order-success-confetti span:nth-child(8)  { left: 83%; background: #06D6A0; animation-delay: 0.75s; border-radius: 50%; }
.order-success-confetti span:nth-child(9)  { left: 92%; background: #118AB2; animation-delay: 0.3s; }
.order-success-confetti span:nth-child(10) { left: 46%; background: #EF476F; animation-delay: 1.3s; border-radius: 50%; }
.order-success-confetti span:nth-child(11) { left: 20%; background: #8B5CF6; animation-delay: 1.6s; }
.order-success-confetti span:nth-child(12) { left: 78%; background: #FFD166; animation-delay: 1.8s; border-radius: 50%; }

@keyframes order-success-fall {
    0%   { transform: translateY(-10px) rotate(0deg); opacity: 0; }
    10%  { opacity: 1; }
    100% { transform: translateY(420px) rotate(340deg); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .order-success-modal,
    .order-success-badge,
    .order-success-confetti span {
        animation: none !important;
    }
}

@media (max-width: 480px) {
    .order-success-modal {
        padding: 32px 22px 24px;
    }
}

/* ---------- Support Tickets list (support.php) ---------- */

.ticket-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ticket-row {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow);
    transition: border-color 0.12s ease, background 0.12s ease;
}

.ticket-row:hover {
    border-color: var(--primary);
    background: var(--surface-raised);
}

.ticket-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.ticket-subject-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.ticket-number {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.ticket-subject {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.ticket-meta {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--muted);
}

.ticket-side {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    white-space: nowrap;
}

.ticket-pill {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: capitalize;
    letter-spacing: 0.04em;
    padding: 3px 10px;
    border-radius: 20px;
    border: 1px solid transparent;
}

.ticket-pill.status-open {
    color: var(--info);
    background: var(--info-tint);
    border-color: rgba(58, 110, 165, 0.25);
}

.ticket-pill.status-in-progress {
    color: var(--warning);
    background: var(--warning-tint);
    border-color: rgba(183, 121, 31, 0.25);
}

.ticket-pill.status-customer-reply {
    color: var(--accent);
    background: var(--accent-tint);
    border-color: rgba(14, 165, 165, 0.3);
}

.ticket-pill.status-answered {
    color: #C23B7A;
    background: rgba(194, 59, 122, 0.12);
    border-color: rgba(194, 59, 122, 0.28);
}

.ticket-pill.status-closed {
    color: var(--muted);
    background: var(--surface-raised);
    border-color: var(--line);
}

.ticket-pill.priority-pill {
    text-transform: uppercase;
}

.ticket-pill.priority-low {
    color: var(--success);
    background: var(--success-tint);
    border-color: rgba(30, 142, 90, 0.25);
}

.ticket-pill.priority-medium {
    color: var(--warning);
    background: var(--warning-tint);
    border-color: rgba(183, 121, 31, 0.25);
}

.ticket-pill.priority-high {
    color: var(--danger);
    background: var(--danger-tint);
    border-color: rgba(192, 57, 43, 0.25);
}

@media (max-width: 640px) {
    .ticket-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .ticket-side {
        align-self: flex-end;
    }
}

/* ---------- New ticket form (ticket-new.php) ---------- */

.ticket-form-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 28px;
    max-width: 640px;
    box-shadow: var(--shadow);
}

/* Centers the card within .content instead of the default left-aligned
   position — opt-in via this modifier since .cart-review-contact-card
   (cart.php) reuses .ticket-form-card inside a two-column grid, where
   left-aligned is correct and centering would fight the grid. Every
   standalone single-form page opts in: account-details.php,
   change-password.php, ticket-new.php, note-edit.php, todo-edit.php,
   volume-partners.php. */
.ticket-form-card.is-centered {
    margin-left: auto;
    margin-right: auto;
}

.ticket-form-card h2 {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 700;
}

.ticket-form-sub {
    margin: 0 0 22px;
    font-size: 13px;
    color: var(--muted);
}

.ticket-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
}

@media (max-width: 520px) {
    .ticket-form-row {
        grid-template-columns: 1fr;
    }
}

/* ---------- Ticket detail / thread (ticket.php) ---------- */

.ticket-detail-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 28px;
    max-width: 760px;
    box-shadow: var(--shadow);
}

.ticket-thread {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin: 22px 0;
}

.ticket-message {
    border-radius: 10px;
    padding: 14px 16px;
    border: 1px solid var(--line);
    background: var(--surface-raised);
}

.ticket-message.is-client {
    background: var(--primary-tint);
    border-color: rgba(29, 78, 216, 0.2);
    margin-left: 8%;
}

.ticket-message.is-staff {
    background: var(--accent-tint);
    border-color: rgba(14, 165, 165, 0.25);
    margin-right: 8%;
}

.ticket-message-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.ticket-message-author {
    font-weight: 600;
    font-size: 13.5px;
}

.ticket-message-role {
    font-family: var(--font-mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.ticket-message-time {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted);
    margin-left: auto;
}

.ticket-message-body {
    font-size: 14px;
    line-height: 1.6;
    white-space: pre-wrap;
}

.ticket-message-attachments {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.ticket-attachment-thumb {
    display: block;
    width: 88px;
    height: 88px;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--line);
    background: var(--surface);
}

.ticket-attachment-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.ticket-reply-form {
    border-top: 1px solid var(--line);
    padding-top: 20px;
    margin-top: 4px;
}

.ticket-closed-note {
    border-top: 1px solid var(--line);
    padding-top: 18px;
    margin-top: 4px;
    font-size: 13.5px;
    color: var(--muted);
}

@media (max-width: 640px) {
    .ticket-message.is-client,
    .ticket-message.is-staff {
        margin-left: 0;
        margin-right: 0;
    }

    .ticket-message-time {
        margin-left: 0;
        width: 100%;
    }
}

/* ---------- Calendar ---------- */
/* Month grid + agenda, driven by invoice due dates and domain expiry
   dates (see public/calendar.php). Dot colours reuse the exact same
   status meaning as .invoice-pill/.domain-pill elsewhere: success =
   paid/active, info = unpaid/pending, warning = expiring soon,
   danger = overdue/expired. */

.calendar-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 20px 22px 16px;
    box-shadow: var(--shadow);
    margin-bottom: 24px;
}

.calendar-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.calendar-nav {
    display: flex;
    align-items: center;
    gap: 14px;
}

.calendar-nav-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 8px;
    border: 1px solid var(--line);
    background: var(--surface-raised);
    color: var(--ink);
    transition: background .15s ease, border-color .15s ease;
}

.calendar-nav-btn:hover {
    background: var(--primary-tint);
    border-color: var(--primary);
    color: var(--primary);
}

.calendar-nav-btn svg {
    width: 16px;
    height: 16px;
}

.calendar-month-label {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 18px;
    color: var(--ink);
    min-width: 140px;
    text-align: center;
}

.calendar-today-link {
    font-size: 14px;
    font-weight: 600;
    color: var(--primary);
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid var(--primary-tint);
    background: var(--primary-tint);
}

.calendar-today-link:hover {
    border-color: var(--primary);
}

.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 6px;
}

.calendar-weekday {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--muted);
    text-align: center;
    padding-bottom: 6px;
}

.calendar-day {
    min-height: 92px;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 6px 6px 8px;
    background: var(--surface-raised);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.calendar-day.is-outside {
    background: var(--surface);
    border-color: var(--line);
    opacity: 0.6;
}

.calendar-day.is-today {
    border-color: var(--primary);
    box-shadow: 0 0 0 1px var(--primary) inset;
}

.calendar-day-num {
    font-family: var(--font-mono);
    font-size: 20px;
    font-weight: 700;
    color: var(--ink);
    line-height: 1.1;
}

.calendar-day.is-outside .calendar-day-num {
    color: var(--muted);
    font-weight: 600;
}

.calendar-day.is-today .calendar-day-num {
    color: var(--primary);
    font-weight: 700;
}

.calendar-day-events {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.calendar-event {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 2px 5px;
    border-radius: 5px;
    background: var(--surface);
    overflow: hidden;
}

.calendar-event:hover {
    background: var(--primary-tint);
}

.calendar-event-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}

.calendar-event-dot.dot-success { background: var(--success); }
.calendar-event-dot.dot-info { background: var(--info); }
.calendar-event-dot.dot-warning { background: var(--warning); }
.calendar-event-dot.dot-danger { background: var(--danger); }

.calendar-event-label {
    font-size: 13px;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.calendar-more {
    font-size: 12px;
    color: var(--muted);
    padding: 0 5px;
}

.calendar-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
}

.calendar-legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--muted);
}

.agenda-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.agenda-section {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 18px 20px;
    box-shadow: var(--shadow);
}

.agenda-heading {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--ink);
    margin: 0 0 12px;
}

.agenda-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.agenda-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 8px;
    border-radius: 8px;
}

.agenda-row:hover {
    background: var(--surface-raised);
}

.agenda-row .calendar-event-dot {
    width: 8px;
    height: 8px;
}

.agenda-date {
    font-family: var(--font-mono);
    font-size: 13px;
    color: var(--muted);
    min-width: 44px;
}

.agenda-body {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.agenda-title {
    font-size: 14.5px;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.agenda-meta {
    font-size: 12.5px;
    color: var(--muted);
}

.agenda-empty {
    font-size: 14.5px;
    color: var(--muted);
}

@media (max-width: 900px) {
    .agenda-grid {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 640px) {
    .calendar-day {
        min-height: 60px;
        padding: 4px;
    }

    .calendar-event-label {
        display: none;
    }

    .calendar-event {
        padding: 2px;
        justify-content: center;
    }

    .calendar-more {
        display: none;
    }

    .calendar-month-label {
        min-width: auto;
        font-size: 16px;
    }
}

@media (max-width: 480px) {
    .calendar-weekday {
        font-size: 10.5px;
    }

    .calendar-day-num {
        font-size: 16px;
    }
}


/* ===== Server Status page ===== */

.status-banner {
    display: flex;
    align-items: center;
    gap: 14px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 16px 20px;
    box-shadow: var(--shadow);
    margin-bottom: 20px;
}

.status-banner.is-ok {
    border-color: rgba(30, 142, 90, 0.3);
    background: var(--success-tint);
}

.status-banner.is-degraded {
    border-color: rgba(183, 121, 31, 0.3);
    background: var(--warning-tint);
}

.status-banner.is-offline {
    border-color: rgba(192, 57, 43, 0.3);
    background: var(--danger-tint);
}

.status-pulse-dot {
    position: relative;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--success);
    flex-shrink: 0;
}

.status-banner.is-degraded .status-pulse-dot {
    background: var(--warning);
}

.status-banner.is-offline .status-pulse-dot {
    background: var(--danger);
}

.status-pulse-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: inherit;
    animation: status-pulse 1.8s ease-out infinite;
}

@keyframes status-pulse {
    0% { transform: scale(1); opacity: 0.6; }
    100% { transform: scale(2.6); opacity: 0; }
}

.status-banner-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    color: var(--ink);
}

.status-banner-sub {
    font-family: var(--font-mono);
    font-size: 11.5px;
    color: var(--muted);
    margin-top: 2px;
}

.status-region-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

.status-region-card {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    box-shadow: var(--shadow);
    text-align: center;
    overflow: hidden;
}

/* Thin status-coloured rail across the top — same green/amber/red
   rollup logic as the page banner, just scoped per region, so a
   client can spot which data-centre needs attention without reading
   every card in the grid below. */
.status-region-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--success);
}

.status-region-card.is-degraded::before { background: var(--warning); }
.status-region-card.is-offline::before { background: var(--danger); }

.status-region-flag {
    font-size: 26px;
    line-height: 1;
    margin-bottom: 8px;
}

.status-region-label {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 14.5px;
    color: var(--ink);
}

.status-region-city {
    font-size: 12px;
    color: var(--muted);
    margin-top: 3px;
}

.status-region-count {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    font-family: var(--font-mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--accent);
    margin-top: 10px;
}

.status-region-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--success);
    flex-shrink: 0;
}

.status-region-card.is-degraded .status-region-dot { background: var(--warning); }
.status-region-card.is-offline .status-region-dot { background: var(--danger); }

.server-rack-card {
    gap: 16px;
    padding-top: 0;
    transition: transform .15s ease, box-shadow .15s ease;
}

.server-rack-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-elevated);
}

/* Dark chassis strip standing in for the front of a physical server —
   rack ears, a vent grille, a "serial" plate, and an LED cluster.
   Bleeds to the card's own edges (negative margin cancelling
   .store-card's padding) and relies on .store-card's overflow:hidden
   to keep its square corners clipped to the card's rounded ones,
   same trick .store-badge-ribbon's diagonal corner already uses. */
.server-chassis {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 46px;
    margin: 0 -22px 0 -22px;
    padding: 0 18px;
    background:
        repeating-linear-gradient(100deg, rgba(255,255,255,.05) 0 1px, transparent 1px 3px),
        linear-gradient(180deg, #232C42 0%, #171E30 100%);
    border-bottom: 1px solid rgba(0, 0, 0, .35);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), inset 0 -6px 10px -8px rgba(0, 0, 0, .6);
    overflow: hidden;
}

[data-theme="dark"] .server-chassis {
    background:
        repeating-linear-gradient(100deg, rgba(255,255,255,.04) 0 1px, transparent 1px 3px),
        linear-gradient(180deg, #10162A 0%, #090D1A 100%);
}

.server-rack-ear {
    position: absolute;
    top: 4px;
    bottom: 4px;
    width: 7px;
    border-radius: 2px;
    background: rgba(0, 0, 0, .35);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
}

.server-rack-ear::before,
.server-rack-ear::after {
    content: "";
    position: absolute;
    left: 50%;
    width: 2.5px;
    height: 2.5px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, rgba(255,255,255,.55), rgba(255,255,255,.08) 65%, transparent 75%);
    transform: translateX(-50%);
}

.server-rack-ear::before { top: 5px; }
.server-rack-ear::after { bottom: 5px; }

.server-rack-ear-left { left: 4px; }
.server-rack-ear-right { right: 4px; }

/* Hot-swap drive bays — reads as an actual server front panel far
   more than a plain vent grille did, and takes up less width, which
   matters on the narrow end of .store-grid's 260px card minimum. */
.server-chassis-bays {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.server-bay {
    position: relative;
    width: 9px;
    height: 23px;
    border-radius: 2px;
    background: linear-gradient(180deg, rgba(255,255,255,.11) 0%, rgba(255,255,255,.03) 100%);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .08);
}

.server-bay::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 50%;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .16);
    transform: translateX(-50%);
}

.server-chassis-id {
    flex: 1;
    min-width: 0;
    text-align: center;
}

.server-chassis-tag {
    font-family: var(--font-mono);
    font-size: 9.5px;
    letter-spacing: 0.1em;
    color: rgba(255, 255, 255, .38);
}

.server-led-cluster {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-shrink: 0;
}

.server-led {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .12);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .3);
}

.server-led-pwr.is-on {
    background: #3FCE8A;
    box-shadow: 0 0 5px 1px rgba(63, 206, 138, .8);
}

/* Activity LED borrows the server's own status colour via currentColor
   so it reads as "this status, blinking" rather than an unrelated
   fourth colour — same online/degraded/offline palette as the status
   LED beside it and the pill up in the card body. */
.server-led-act {
    background: currentColor;
    color: rgba(255, 255, 255, .16);
}

.server-led-act.status-online { color: #3FCE8A; }
.server-led-act.status-paused { color: #E3AC4E; }
.server-led-act.status-offline { color: rgba(255, 255, 255, .16); }

.server-led-act.is-blinking {
    animation: server-led-blink 1.4s steps(1, end) infinite;
}

@keyframes server-led-blink {
    0%, 45% { opacity: 1; box-shadow: 0 0 5px 1px currentColor; }
    50%, 100% { opacity: .3; box-shadow: none; }
}

.server-led-stat.status-online { background: #3FCE8A; box-shadow: 0 0 5px 1px rgba(63, 206, 138, .8); }
.server-led-stat.status-paused { background: #E3AC4E; box-shadow: 0 0 5px 1px rgba(227, 172, 78, .8); }
.server-led-stat.status-offline { background: #F0685A; box-shadow: 0 0 5px 1px rgba(240, 104, 90, .8); }

.status-server-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
}

.status-server-top .store-card-name {
    padding-right: 0;
    font-size: 16px;
}

.status-server-top .store-card-tagline {
    margin: 0;
}

.status-server-location {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: var(--muted);
}

.status-server-stats {
    display: flex;
    gap: 10px;
}

/* Small LCD/LED-readout look for the two figures a client actually
   checks mid-incident — light inset panel (was a dark one, see this
   file's own top comment on dropping dark surfaces everywhere), mono
   digits still tinted the same accent green a server's own front-panel
   display would use, just solid instead of glowing since a glow only
   reads as "lit up" against a dark backing. */
.status-server-stat {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--surface-raised);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 8px 10px;
    box-shadow: inset 0 1px 2px rgba(11, 27, 59, .06);
}

.status-server-stat-label {
    font-family: var(--font-mono);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
}

.status-server-stat-value {
    font-family: var(--font-mono);
    font-weight: 500;
    font-size: 15px;
    letter-spacing: 0.02em;
    color: var(--success);
}

.status-server-stat-bar {
    display: block;
    height: 3px;
    border-radius: 2px;
    background: var(--line);
    overflow: hidden;
    margin-top: 1px;
}

.status-server-stat-bar-fill {
    display: block;
    height: 100%;
    border-radius: 2px;
}

@media (max-width: 640px) {
    .status-banner {
        flex-direction: row;
        align-items: flex-start;
    }
}

@media (prefers-reduced-motion: reduce) {
    .status-pulse-dot::after,
    .server-led-act.is-blinking {
        animation: none;
    }
}

/* ---------------------------------------------------------------
   Floating action stack — chat
   Sits bottom-right on every page (wired up in partials/footer.php).
   Fades/scales in on load. (Used to be a two-button stack with a
   back-to-top FAB sitting below this one — removed; this button now
   takes that lower slot on its own, and the chat window above it was
   shifted down to match — see .chat-window's own comment.)
------------------------------------------------------------------ */
.fab-chat {
    position: fixed;
    right: 24px;
    /* Used to reserve room for .fab-top sitting below it (bottom:
       calc(147px + ...)) — that button is gone now, so this one drops
       into its old slot instead. The env() term still adds however
       much the device reserves for its own bottom UI (home-indicator/
       gesture-nav bar) on top of the base offset, so this button never
       renders underneath it; resolves to 0 on devices/browsers with no
       safe area (falls back to plain 24px). */
    bottom: calc(60px + env(safe-area-inset-bottom, 0px));
    z-index: 200;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: linear-gradient(180deg, var(--primary) 0%, var(--primary-shade) 100%);
    color: #fff;
    font: 600 14px/1 var(--font-body);
    cursor: pointer;
    /* Own shadow instead of var(--shadow-elevated): that variable's
       0 24px 48px -16px layer is a downward-biased card shadow that
       read as too heavy at this button's size. This is symmetric and
       stays tight to the circle instead. */
    box-shadow: 0 2px 6px rgba(11,27,59,.16), 0 8px 16px -6px rgba(11,27,59,.24);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    transform: translateY(24px) scale(.85);
    opacity: 0;
    animation: fabPopIn .5s cubic-bezier(.34,1.56,.64,1) .3s forwards;
    transition: transform .2s ease, box-shadow .2s ease;
}
.fab-chat:hover {
    transform: translateY(-3px) scale(1.03);
    box-shadow: 0 4px 8px rgba(11,27,59,.2), 0 10px 20px -6px rgba(11,27,59,.32);
}
.fab-chat:active { transform: translateY(-1px) scale(.98); }
.fab-chat-icon-wrap {
    position: relative;
    display: grid;
    place-items: center;
    flex: 0 0 46px;
    width: 46px;
    height: 46px;
}
.fab-chat-icon-wrap::before {
    content: "";
    position: absolute;
    inset: 5px;
    border-radius: 50%;
    background: rgba(255,255,255,.22);
    animation: fabPulseRing 2.4s ease-out infinite;
}
.fab-chat-icon-wrap svg { position: relative; width: 20px; height: 20px; }
/* .fab-chat-label markup still exists in footer.php's DOM but is never
   shown now — the button is an icon-only circle at every width, so the
   label span just sits there hidden. */
.fab-chat-label { display: none; }
/* Unread-count pill, not just a presence dot — same shape/colour as
   the topbar bell's .notif-badge (danger-red, mono digits, white ring)
   so an unread count reads the same way anywhere in this app. Sized to
   fit "9" up through "99+" without the pill changing height. */
.fab-chat-badge {
    position: absolute;
    top: 0;
    right: 1px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    line-height: 17px;
    text-align: center;
    box-shadow: 0 0 0 2px #fff;
}

@keyframes fabPopIn {
    from { opacity: 0; transform: translateY(24px) scale(.85); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes fabPulseRing {
    0%   { transform: scale(.7); opacity: .9; }
    70%  { transform: scale(1.9); opacity: 0; }
    100% { transform: scale(1.9); opacity: 0; }
}

/* ---------------------------------------------------------------
   Floating action — Login to Old Dashboard
   Bottom-left counterpart to .fab-chat's bottom-right stack, wired
   up in partials/footer.php the same way. Plain external link to the
   previous client portal (dashboard.vikalink.com) — unlike .fab-chat
   it isn't gated on a signed-in $chatClient, so it renders on every
   page that includes footer.php regardless of chat state. Pill-shaped
   with a visible label (rather than icon-only like .fab-chat) since
   it's a less-frequent, more-deliberate action a client needs to be
   able to identify at a glance, not a persistent quick-access tool.
------------------------------------------------------------------ */
.fab-old-dashboard {
    position: fixed;
    left: 24px;
    bottom: calc(24px + env(safe-area-inset-bottom, 0px));
    z-index: 200;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding-right: 16px;
    height: 46px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    font: 600 13px/1 var(--font-body);
    text-decoration: none;
    white-space: nowrap;
    box-shadow: 0 2px 6px rgba(11,27,59,.14), 0 8px 16px -6px rgba(11,27,59,.2);
    transform: translateY(24px) scale(.85);
    opacity: 0;
    animation: fabPopIn .5s cubic-bezier(.34,1.56,.64,1) .3s forwards;
    transition: transform .2s ease, box-shadow .2s ease, background .15s ease, border-color .15s ease;
}
.fab-old-dashboard:hover {
    background: var(--primary-tint);
    border-color: var(--primary);
    transform: translateY(-3px) scale(1.03);
    box-shadow: 0 4px 8px rgba(11,27,59,.18), 0 10px 20px -6px rgba(11,27,59,.28);
}
.fab-old-dashboard:active { transform: translateY(-1px) scale(.98); }
.fab-old-dashboard-icon {
    display: grid;
    place-items: center;
    flex: 0 0 46px;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: var(--primary-tint);
    color: var(--primary);
}
.fab-old-dashboard-icon svg { width: 18px; height: 18px; }

@media (max-width: 640px) {
    .fab-old-dashboard {
        left: 16px;
        bottom: calc(20px + env(safe-area-inset-bottom, 0px));
        padding-right: 0;
        gap: 0;
    }
    /* Icon-only pill on small screens, same "collapse the label"
       treatment .fab-chat's own (now-unused) label rule follows —
       keeps this from crowding a phone-width footer/cart-drawer. */
    .fab-old-dashboard-label { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .fab-old-dashboard { animation: none; opacity: 1; transform: none; }
}

/* Sidebar collision — on pages built from dashboard.php (i.e. every
   logged-in client page), the sidebar and this FAB were both anchored
   to bottom-left, so the FAB (z-index: 200) rendered directly on top
   of .sidebar-signout. Above the 900px breakpoint the sidebar is
   permanently visible at left:0, width var(--sidebar-width), so push
   the FAB past it instead of overlapping. */
@media (min-width: 901px) {
    .fab-old-dashboard {
        left: calc(var(--sidebar-width) + 24px);
    }
}

/* Below 900px the sidebar is normally off-canvas (see the mobile
   .sidebar rule), so the FAB has that corner to itself — but while
   the drawer is open (.app-shell.sidebar-open) it slides over that
   same corner again. Sign out is already reachable in the open
   drawer, so just hide the redundant FAB rather than relocate it. */
@media (max-width: 900px) {
    .app-shell.sidebar-open .fab-old-dashboard {
        opacity: 0;
        pointer-events: none;
    }
}

/* ---------------------------------------------------------------
   Chat window — the slide-up panel .fab-chat above opens/closes.
   Fixed above .fab-chat, same right edge, so the two always feel
   like one stack. Bottom offset shifted down alongside .fab-chat's
   own (see that rule's comment on the removed back-to-top button) —
   same 123px drop, keeping the same ~23px gap above the button.
   Starts `hidden` (display:none) in the markup; assets/chat-widget.js
   clears that and adds .is-open a frame later for the scale/slide-in
   transition, same hidden-then-classList-toggle shape footer.php's
   own domain upsell overlay already uses elsewhere in this file.
------------------------------------------------------------------ */
.chat-window {
    position: fixed;
    right: 24px;
    bottom: 83px;
    z-index: 210;
    width: 360px;
    max-width: calc(100vw - 32px);
    height: 620px;
    max-height: calc(100vh - 140px - var(--chat-kb-offset, 0px));
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-elevated);
    overflow: hidden;
    transform-origin: bottom right;
    transform: translateY(16px) scale(.96);
    opacity: 0;
    pointer-events: none;
    transition: transform .22s cubic-bezier(.34,1.56,.64,1), opacity .18s ease;
}
.chat-window.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
/* Belt-and-suspenders alongside .is-open's opacity/pointer-events
   toggle: same `display` vs `[hidden]` tie described above, kept here
   too so the panel is properly removed from layout/the a11y tree
   while closed, not just faded out and click-through-disabled. */
.chat-window[hidden] {
    display: none;
}
.chat-window-head {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 14px 12px 16px;
    background: linear-gradient(180deg, var(--primary) 0%, var(--primary-shade) 100%);
    color: #fff;
}
.chat-window-head-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.chat-window-head-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.chat-window-title { font: 700 15px/1.2 var(--font-display); }
.chat-window-subtitle { font: 400 12px/1.3 var(--font-body); opacity: .85; }
.chat-window-close {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
    color: #fff;
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: background .15s ease;
}
.chat-window-close:hover { background: rgba(255, 255, 255, .32); }
.chat-window-close svg { width: 14px; height: 14px; }

/* Quick-contact strip (Call / WhatsApp / Ticket) — sits right under the
   subtitle, inside the header's own gradient, rather than as a separate
   card-style row above the messages. Deliberately no background/border
   per tile (that "card" look is what ate space and, on a short mobile
   viewport, pushed the actual chat log down to a couple of visible
   lines) — just a small colour-coded icon and a label, small enough
   that the row adds only ~40px to the header instead of a full extra
   section. */
.chat-quick-actions {
    display: flex;
    align-items: center;
    gap: 6px;
}
.chat-quick-action {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 6px 4px;
    border-radius: 8px;
    text-decoration: none;
    color: rgba(255, 255, 255, .92);
    font: 600 11px/1.2 var(--font-body);
    text-align: center;
    transition: background .15s ease;
}
.chat-quick-action:hover {
    background: rgba(255, 255, 255, .14);
    color: #fff;
}
.chat-quick-action:active { background: rgba(255, 255, 255, .22); }
.chat-quick-action-icon {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: rgba(255, 255, 255, .92);
}
.chat-quick-action-icon svg { width: 12px; height: 12px; }
.chat-quick-action-phone .chat-quick-action-icon { color: var(--primary); }
.chat-quick-action-whatsapp .chat-quick-action-icon { color: #128C7E; }
.chat-quick-action-ticket .chat-quick-action-icon { color: var(--accent); }
.chat-messages {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 14px 14px 6px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--bg);
}
.chat-empty {
    margin: auto;
    max-width: 220px;
    text-align: center;
    color: var(--muted);
    font: 400 13px/1.5 var(--font-body);
}

/* Pre-chat intake (topic picker + self-service links) — see footer.php's
   own docblock on #chatIntake. Rendered as a card sitting at the top of
   #chatMessages (not centered like #chatEmpty) so it reads as an
   onboarding step rather than a placeholder. */
.chat-intake {
    flex: 0 0 auto;
    padding: 12px;
    border-radius: 12px;
    background: var(--surface);
    box-shadow: var(--shadow-tile);
}
.chat-intake-prompt {
    margin: 0 0 8px;
    font: 700 12.5px/1.3 var(--font-body);
    color: var(--ink);
}
.chat-topic-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.chat-topic-btn {
    padding: 6px 10px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--ink);
    font: 600 11.5px/1.2 var(--font-body);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.chat-topic-btn:hover { background: var(--primary-tint); border-color: var(--primary); }
.chat-topic-btn.is-selected { background: var(--primary); border-color: var(--primary); color: #fff; }
.chat-topic-btn.is-urgent { color: var(--danger); border-color: var(--danger-tint); }
.chat-topic-btn.is-urgent:hover { background: var(--danger-tint); border-color: var(--danger); }
.chat-topic-btn.is-urgent.is-selected { background: var(--danger); border-color: var(--danger); color: #fff; }
.chat-selfservice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--line);
}
.chat-selfservice-label {
    margin: 0;
    flex: 0 0 100%;
    font: 500 11px/1.3 var(--font-body);
    color: var(--muted);
}
.chat-selfservice-link {
    font: 600 11.5px/1.2 var(--font-body);
    color: var(--primary);
    text-decoration: none;
}
.chat-selfservice-link:hover { text-decoration: underline; }

/* Quick-request buttons (#chatQuickRequests) — one click posts a
   pre-written message via chat-send.php's 'quick_action' field (see
   CHAT_QUICK_ACTIONS, chat_data.php). Sits between the message list
   and the input form, always visible (unlike .chat-intake above,
   which only shows before a thread's first message) — smaller/more
   muted than .chat-topic-btn since these are a secondary shortcut,
   not the primary way to start a conversation. */
.chat-quick-requests {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding: 0 12px 8px;
}
.chat-quick-request-btn {
    padding: 5px 9px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--muted);
    font: 600 11px/1.2 var(--font-body);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chat-quick-request-btn:hover:not(:disabled) { background: var(--primary-tint); border-color: var(--primary); color: var(--primary); }
.chat-quick-request-btn:disabled { opacity: .55; cursor: default; }

/* "Support is typing…" — three dots, staggered bounce. Always the last
   child of #chatMessages while visible (chat-widget.js re-appends it),
   so it reads as coming right after the newest bubble. */
.chat-typing-indicator {
    align-self: flex-start;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 9px 12px;
    border-radius: 14px;
    border-bottom-left-radius: 4px;
    background: var(--surface);
    box-shadow: var(--shadow-tile);
}
/* Same `display` vs `[hidden]` specificity tie as .bulk-actions-bar
   above — without this, chat-widget.js's
   `typingIndicatorEl.hidden = false/true` toggle never actually hid
   the dots once they'd shown once, so "Support is typing…" stuck on
   screen permanently. */
.chat-typing-indicator[hidden] {
    display: none;
}
.chat-typing-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--muted);
    opacity: .5;
    animation: chatTypingBounce 1.1s ease-in-out infinite;
}
.chat-typing-dot:nth-child(2) { animation-delay: .15s; }
.chat-typing-dot:nth-child(3) { animation-delay: .3s; }
@keyframes chatTypingBounce {
    0%, 60%, 100% { transform: translateY(0); opacity: .5; }
    30% { transform: translateY(-3px); opacity: 1; }
}

/* Star-rating prompt — sits between the message list and the reply
   form, same "slim strip" footprint as #chatStatus right below it. */
.chat-rating-prompt {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 10px 30px 10px 14px;
    border-top: 1px solid var(--line);
    background: var(--primary-tint);
}
/* Same `display` vs `[hidden]` tie as .chat-typing-indicator above —
   without this, clicking the × (#chatRatingDismiss) or submitting a
   star rating set `ratingPromptEl.hidden = true` in chat-widget.js
   but the strip (and its close button) stayed on screen regardless. */
.chat-rating-prompt[hidden] {
    display: none;
}
.chat-rating-prompt-text { margin: 0; font: 600 12px/1.3 var(--font-body); color: var(--ink); }
.chat-rating-stars { display: flex; gap: 4px; }
.chat-rating-star {
    border: none;
    background: none;
    padding: 0;
    font-size: 22px;
    line-height: 1;
    color: var(--line);
    cursor: pointer;
    transition: color .12s ease, transform .12s ease;
}
.chat-rating-star:hover { color: #f59e0b; transform: scale(1.12); }
.chat-rating-star.is-filled { color: #f59e0b; }
.chat-rating-dismiss {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--muted);
    display: grid;
    place-items: center;
    cursor: pointer;
}
.chat-rating-dismiss:hover { background: rgba(0,0,0,.06); }
.chat-rating-dismiss svg { width: 12px; height: 12px; }

.chat-msg { display: flex; }
.chat-msg-in { justify-content: flex-start; }
.chat-msg-out { justify-content: flex-end; }
.chat-msg-bubble {
    max-width: 78%;
    padding: 8px 12px;
    border-radius: 14px;
    box-shadow: var(--shadow-tile);
}
.chat-msg-in .chat-msg-bubble {
    background: var(--surface);
    color: var(--ink);
    border-bottom-left-radius: 4px;
}
.chat-msg-out .chat-msg-bubble {
    background: var(--primary);
    color: #fff;
    border-bottom-right-radius: 4px;
}
.chat-msg-body { font: 400 13.5px/1.45 var(--font-body); white-space: pre-wrap; word-break: break-word; }
.chat-msg-meta { margin-top: 3px; font: 500 10.5px/1.3 var(--font-body); opacity: .7; }
.chat-msg-out .chat-msg-meta { text-align: right; }
.chat-msg-image-link { display: block; }
.chat-msg-image {
    display: block;
    max-width: 100%;
    max-height: 220px;
    border-radius: 10px;
    object-fit: cover;
}
.chat-msg-body + .chat-msg-image-link,
.chat-msg-image-link + .chat-msg-body { margin-top: 6px; }

.chat-status {
    flex: 0 0 auto;
    margin: 0;
    padding: 7px 14px;
    font: 500 12px/1.4 var(--font-body);
    color: var(--danger);
    background: var(--danger-tint);
    border-top: 1px solid var(--line);
}

.chat-window-form {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid var(--line);
    background: var(--surface);
}
.chat-input {
    flex: 1 1 auto;
    resize: none;
    min-height: 36px;
    max-height: 90px;
    padding: 8px 12px;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--surface-raised);
    color: var(--ink);
    font: 400 13.5px/1.4 var(--font-body);
}
.chat-input:focus { outline: none; border-color: var(--primary); }
.chat-attach-btn {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--surface-raised);
    color: var(--muted);
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.chat-attach-btn:hover { background: var(--primary-tint); color: var(--primary); }
.chat-attach-btn:disabled { opacity: .5; cursor: default; }
.chat-attach-btn svg { width: 16px; height: 16px; }
.chat-send-btn {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: background .15s ease;
}
.chat-send-btn:hover { background: var(--primary-shade); }
.chat-send-btn:disabled { opacity: .5; cursor: default; }
.chat-send-btn svg { width: 16px; height: 16px; }

/* Manual Tawk.to handoff strip — sits below .chat-window-form, at the
   very bottom of the chat window. Deliberately small/secondary next
   to the message composer above it (this is an escape hatch, not the
   primary action), but the pulsing dot borrows .status-pulse's exact
   ring animation so it still reads as "live" at a glance. */
.chat-quickchat-btn {
    flex: 0 0 auto;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    border: none;
    border-top: 1px solid var(--line);
    background: var(--surface-raised);
    color: var(--ink);
    text-align: left;
    cursor: pointer;
    transition: background .15s ease;
}
.chat-quickchat-btn:hover { background: var(--primary-tint); }
.chat-quickchat-btn:active { background: var(--primary-tint); }
.chat-quickchat-pulse-dot {
    position: relative;
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
}
.chat-quickchat-pulse-dot::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: inherit;
    animation: status-pulse 1.8s ease-out infinite;
}
.chat-quickchat-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.chat-quickchat-label {
    font: 700 12.5px/1.2 var(--font-display);
    color: var(--ink);
}
.chat-quickchat-sub {
    font: 400 11px/1.3 var(--font-body);
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.chat-quickchat-btn svg {
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    color: var(--muted);
    transition: transform .15s ease;
}
.chat-quickchat-btn:hover svg { transform: translateX(2px); color: var(--primary); }

@media (max-width: 640px) {
    .fab-chat { right: 16px; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); }
    /* Pinned on BOTH top and bottom (not just bottom + a vh-based
       max-height) so the panel resizes to whatever room is actually
       available instead of sliding upward off-screen. That upward
       slide — clipping the header/title/close button above the top
       of the screen — is what happens when only `bottom` + a fixed
       `max-height: calc(100vh - Npx)` are used: opening the chat
       focuses the input, the mobile keyboard appears, and iOS/Android
       nudge the whole (scrollable) page to keep the focused input in
       view, dragging this fixed panel along with it while its height
       stays locked to the pre-keyboard 100vh. `--chat-kb-offset` is
       kept at 0 by default and only pushed above 0px by the
       visualViewport listener in chat-widget.js while the on-screen
       keyboard is open, so the panel actively lifts clear of it. */
    .chat-window {
        right: 12px;
        left: 12px;
        width: auto;
        top: max(12px, env(safe-area-inset-top, 0px));
        bottom: calc(39px + env(safe-area-inset-bottom, 0px) + var(--chat-kb-offset, 0px));
        height: auto;
        max-height: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .fab-chat { animation: none; opacity: 1; transform: none; }
    .fab-chat-icon-wrap::before { animation: none; }
    .chat-window { transition: opacity .1s linear; }
}

/* ---------- Cart Drawer (partials/cart-drawer.php) ----------
   Slide-over panel replacing the old cart.php full page — standard
   e-commerce cart pattern. Sits on top of whatever page the client is
   already on, opened from the topbar .cart-toggle button. */

.cart-drawer-overlay {
    position: fixed;
    inset: 0;
    background: rgba(11, 27, 59, 0.45);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    z-index: 110;
    opacity: 0;
    transition: opacity .2s ease;
    display: flex;
    justify-content: flex-end;
}

.cart-drawer-overlay[hidden] { display: none; }

.cart-drawer-overlay.is-open { opacity: 1; }

.cart-drawer {
    position: relative;
    width: 100%;
    max-width: 400px;
    height: 100%;
    background: var(--surface);
    box-shadow: var(--shadow-elevated);
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform .24s cubic-bezier(.22, .85, .32, 1.1);
}

.cart-drawer-overlay.is-open .cart-drawer {
    transform: translateX(0);
}

.cart-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 18px 20px;
    border-bottom: 1px solid var(--line);
    flex-shrink: 0;
}

.cart-drawer-head h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--ink);
    margin: 0;
}

.cart-drawer-head h2 svg { width: 19px; height: 19px; color: var(--primary); }

.cart-drawer-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--primary-tint);
    color: var(--primary);
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
}

.cart-drawer-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    border: none;
    background: var(--surface-raised);
    color: var(--muted);
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.cart-drawer-close:hover { background: var(--line); color: var(--ink); }
.cart-drawer-close svg { width: 16px; height: 16px; }

.cart-drawer-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 8px 12px;
}

.cart-drawer-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 12px;
    padding: 60px 24px;
    color: var(--muted);
}

.cart-drawer-empty svg {
    width: 46px;
    height: 46px;
    color: var(--line);
}

.cart-drawer-empty p {
    margin: 0;
    font-size: 14px;
}

.cart-drawer-empty .order-btn-primary,
.cart-drawer-empty .order-btn-secondary {
    width: 100%;
    max-width: 220px;
    justify-content: center;
}

.cart-drawer-items {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.cart-drawer-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 8px;
    border-radius: var(--radius);
    transition: background .12s ease;
}

.cart-drawer-item:hover { background: var(--surface-raised); }

.cart-drawer-item-icon {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: var(--primary-tint);
    color: var(--primary);
}

.cart-drawer-item-icon svg { width: 17px; height: 17px; }

.cart-drawer-item-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cart-drawer-item-label {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cart-drawer-item-price {
    font-family: var(--font-mono);
    font-size: 12.5px;
    color: var(--muted);
}

.cart-drawer-item-remove {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    border: none;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: background .12s ease, color .12s ease;
}

.cart-drawer-item-remove:hover { background: var(--danger-tint); color: var(--danger); }
.cart-drawer-item-remove svg { width: 14px; height: 14px; }
.cart-drawer-item-remove:disabled { opacity: .5; cursor: default; }

.cart-drawer-footer {
    flex-shrink: 0;
    border-top: 1px solid var(--line);
    padding: 16px 20px 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.cart-drawer-coupon {
    display: flex;
    gap: 8px;
}

.cart-drawer-coupon input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 9px 12px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: var(--surface-raised);
    color: var(--ink);
    font-size: 13px;
}

.cart-drawer-coupon input:focus {
    outline: none;
    border-color: var(--primary);
}

.cart-drawer-coupon-status,
.cart-drawer-status {
    margin: -4px 0 0;
    font-size: 12.5px;
    color: var(--success);
}

.cart-drawer-coupon-status.is-error,
.cart-drawer-status.is-error { color: var(--danger); }

.cart-drawer-total-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
    padding-top: 4px;
    border-top: 1px dashed var(--line);
}

.cart-drawer-total-row span:last-child {
    font-family: var(--font-mono);
    color: var(--primary);
}

.cart-drawer-checkout {
    width: 100%;
    justify-content: center;
}

.cart-drawer-trust-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    justify-content: center;
    font-size: 11px;
    color: var(--muted);
}

body.cart-drawer-open { overflow: hidden; }

@media (max-width: 480px) {
    .cart-drawer { max-width: 100%; }
}

/* ---------- PWA install banner (assets/pwa-install.js) ---------- */

.pwa-install-banner {
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%) translateY(120%);
    z-index: 120;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: calc(100vw - 32px);
    width: 380px;
    /* Extra right padding clears room for the close button, which is
       now pinned to the card's top-right corner (see
       .pwa-install-banner-dismiss below) instead of sitting inline at
       the end of .pwa-install-banner-actions — inline, it landed at
       the card's bottom-right corner, which is exactly where
       .fab-chat (z-index 200, vs this card's 120) sits, so the close
       button was rendering underneath the chat launcher and could
       never be tapped. */
    padding: 14px 34px 14px 16px;
    border-radius: 14px;
    background: var(--surface);
    border: 1px solid var(--line);
    box-shadow: var(--shadow-elevated);
    transition: transform .3s cubic-bezier(.22, .85, .32, 1.1);
}

.pwa-install-banner.is-visible {
    transform: translateX(-50%) translateY(0);
}

.pwa-install-banner img {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    flex-shrink: 0;
}

.pwa-install-banner-body {
    flex: 1 1 auto;
    min-width: 0;
}

.pwa-install-banner-title {
    display: block;
    font-family: var(--font-display);
    font-size: 13.5px;
    font-weight: 700;
    color: var(--ink);
}

.pwa-install-banner-sub {
    display: block;
    font-size: 12px;
    color: var(--muted);
    margin-top: 1px;
}

.pwa-install-banner-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.pwa-install-banner-install {
    padding: 7px 12px;
    border-radius: 999px;
    border: none;
    background: var(--primary);
    color: #fff;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
}

.pwa-install-banner-dismiss {
    position: absolute;
    top: 6px;
    right: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 999px;
    border: none;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
}

.pwa-install-banner-dismiss svg { width: 13px; height: 13px; }

@media (max-width: 480px) {
    .pwa-install-banner { width: calc(100vw - 24px); bottom: 12px; }
}

/* ---------- Cart Review (cart.php) ----------
   Full-page equivalent of the cart drawer's item list, plus the
   per-item WHOIS Privacy / Auto-Renew / Nameservers options that used
   to live on order.php's own Review step. Item rows reuse the
   drawer's .cart-drawer-item-icon/-body/-label/-price so a domain or
   product line looks identical whether it's read from the drawer or
   this page; everything below is layout new to this page. */

.cart-review-card {
    max-width: 720px;
    margin: 0 auto;
}

.cart-review-list {
    list-style: none;
    margin: 0 0 20px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.cart-review-item {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 16px 18px;
    box-shadow: var(--shadow);
}

.cart-review-item-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.cart-review-item-head .cart-drawer-item-body {
    gap: 3px;
}

.cart-review-item-head .cart-drawer-item-label {
    white-space: normal;
    font-size: 14.5px;
}

.cart-review-item-head .cart-drawer-item-price {
    font-size: 13px;
    color: var(--primary);
}

.cart-review-options {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--line);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.cart-review-option-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.cart-review-option-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.cart-review-option-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--ink);
}

.cart-review-option-hint {
    font-size: 11.5px;
    color: var(--muted);
}

/* Servers store OS choice, display-only (cart.php) — same dashed
   divider as .cart-review-options above, but its own block since it
   isn't a togglable option row like WHOIS Privacy/Auto-Renew. */
.cart-review-os-line {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-size: 13px;
    color: var(--ink);
}

.cart-review-ns-block {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.cart-review-ns-block .ns-mode-choice,
.cart-review-ns-block .ns-field-grid {
    margin-top: 0;
}

.cart-review-summary {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 18px 20px;
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.cart-review-summary-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--ink);
}

.cart-review-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
    padding: 80px 24px;
    color: var(--muted);
}

.cart-review-empty svg {
    width: 52px;
    height: 52px;
    color: var(--line);
}

.cart-review-empty p {
    margin: 0;
    font-size: 14.5px;
}

.cart-review-empty-actions {
    display: flex;
    gap: 10px;
}

.cart-review-contact-card {
    margin-bottom: 20px;
}

.cart-review-contact-value {
    margin: 2px 0 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
}

.cart-review-contact-value.is-missing {
    font-weight: 500;
    font-style: italic;
    color: var(--muted);
}

.cart-review-contact-edit {
    display: inline-flex;
    margin-top: 4px;
}

.cart-review-confirm-row {
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px dashed var(--line);
}

/* ---------- Provisioning screen (provisioning.php) ---------- */

.provisioning-card {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 18px;
    padding: 40px 32px 34px;
    max-width: 520px;
    margin: 0 auto;
    box-shadow: var(--shadow-elevated);
    text-align: center;
}

.provisioning-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 5px;
    background: linear-gradient(90deg, var(--primary), var(--accent));
}

.provisioning-badge {
    width: 68px;
    height: 68px;
    margin: 0 auto 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--success-tint);
    color: var(--success);
    animation: provisioning-badge-pop 0.55s cubic-bezier(.25, 1.6, .4, 1) 0.1s both;
}

.provisioning-badge svg {
    width: 30px;
    height: 30px;
}

@keyframes provisioning-badge-pop {
    0% { transform: scale(0) rotate(-20deg); }
    70% { transform: scale(1.1) rotate(3deg); }
    100% { transform: scale(1) rotate(0deg); }
}

.provisioning-title {
    margin: 0 0 8px;
    font-family: var(--font-display);
    font-size: 21px;
    font-weight: 800;
    color: var(--ink);
    letter-spacing: -0.01em;
}

.provisioning-subtitle {
    margin: 0 0 26px;
    font-size: 14px;
    line-height: 1.55;
    color: var(--muted);
}

.provisioning-steps {
    list-style: none;
    margin: 0 0 22px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: left;
}

.provisioning-step {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 12px;
    background: var(--bg);
    border: 1px solid var(--line);
    transition: background 0.2s ease, border-color 0.2s ease;
}

.provisioning-step-icon {
    position: relative;
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

.provisioning-step-check {
    width: 20px;
    height: 20px;
    color: var(--success);
    opacity: 0;
    transform: scale(0.6);
    transition: opacity 0.25s ease, transform 0.25s cubic-bezier(.25, 1.6, .4, 1);
}

.provisioning-step-spinner {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2.5px solid var(--line);
    border-top-color: var(--primary);
    animation: provisioning-spin 0.8s linear infinite;
}

.provisioning-step.is-done {
    background: var(--success-tint);
    border-color: transparent;
}

.provisioning-step.is-done .provisioning-step-check {
    opacity: 1;
    transform: scale(1);
}

.provisioning-step.is-done .provisioning-step-spinner {
    display: none;
}

.provisioning-step-label {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--ink);
}

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

.provisioning-note {
    margin: 0 0 22px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--muted);
}

.provisioning-note a {
    color: var(--primary);
    font-weight: 600;
    text-decoration: none;
}

.provisioning-note a:hover {
    text-decoration: underline;
}

.provisioning-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
}

@media (prefers-reduced-motion: reduce) {
    .provisioning-badge,
    .provisioning-step-spinner,
    .provisioning-step-check {
        animation: none !important;
        transition: none !important;
    }
}

@media (max-width: 480px) {
    .provisioning-card {
        padding: 30px 20px 26px;
    }

    .provisioning-actions {
        flex-direction: column;
    }
}

/* ---------- Order Confirmation (order-confirmation.php) ----------
   Built on .provisioning-card's shell rather than .invoice-detail-card:
   it's already centered (text-align: center, margin: 0 auto) and
   already proven not to shift or force zoom on a phone (see its own
   480px rule above), which is exactly what a "you just ordered this"
   screen needs — invoice.php's wider, left-aligned layout is for
   scanning a real bill, not a one-glance confirmation. */
.confirmation-card {
    /* A little wider than the base 520px so the two-column meta grid
       and receipt rows below have room to breathe on tablets — still
       shrinks and stacks the same way on phones via the rules below. */
    max-width: 560px;
}

.confirmation-status-pill {
    display: inline-block;
    margin: 2px 0 22px;
}

.confirmation-items {
    display: flex;
    flex-direction: column;
    margin: 0 0 24px;
    border-top: 1px solid var(--line);
    text-align: left;
}

.confirmation-item-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--line);
}

.confirmation-item-desc {
    font-size: 14px;
    color: var(--ink);
    /* Long product/domain names wrap onto their own centered line
       (mobile) rather than pushing the amount column sideways. */
    overflow-wrap: anywhere;
}

.confirmation-item-amount {
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
}

.confirmation-item-row.confirmation-item-total {
    border-bottom: none;
    padding-top: 16px;
}

.confirmation-item-total .confirmation-item-desc {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
}

.confirmation-item-total .confirmation-item-amount {
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 700;
    color: var(--primary);
}

@media (max-width: 480px) {
    /* Same reasoning as .detail-header's own 640px fix earlier in this
       file: a long line-item description sitting next to a
       right-aligned price on a narrow phone is exactly the kind of
       two-column squeeze that reads as the page "shifting" sideways.
       Stacking each row — description first, price directly under it —
       removes that squeeze and keeps every line centered under the
       card, matching the rest of this screen. */
    .confirmation-item-row {
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 4px;
    }
}
