/*
 * The customer panel's design system: hosting cards, the .chb-ds-* domain
 * basket, badges, dashboard rows, CTA buttons, plus two Filament tweaks (the
 * "between"-aligned modal footer and the tinted sidebar). Published to
 * public/ by `php artisan filament:assets` (runs as part of composer's
 * post-autoload-dump via filament:upgrade) and loaded only on the customer
 * panel via ->assets() in CustomerPanelProvider.
 */

/* The "between"-aligned modal footer fix lives in the shared
   filament/shared/tweaks.css asset (both panels need it). */
/* Filament makes the desktop sidebar transparent by
   default, so it blends into the page body. Pin it to
   the very same variables the topbar uses so the menu
   matches the header exactly (light + dark). */
.fi-sidebar.fi-main-sidebar {
    background-color: var(--color-white);
    border-right: 1px solid color-mix(in oklab, var(--gray-950) 5%, transparent);
}
.dark .fi-sidebar.fi-main-sidebar {
    background-color: var(--gray-900);
    border-right-color: rgba(255, 255, 255, 0.06);
}

/* Solid action buttons across the customer panel darken
   on hover (a "press" feel) instead of Filament's default
   brighten. One rule covers every solid colour — primary,
   success, danger — by darkening the button's own
   --color-600. This plain rule wins over Filament's
   @layer-ed hover in both light and dark mode. */
:is(.fi-btn:not(.fi-outlined).fi-color:not(label)):hover {
    background-color: color-mix(in oklab, var(--color-600) 80%, black);
}

/* Render the hosting-order radio as a row of selectable
   pricing cards (see ViewDomain::orderHostingAction). */
.fi-hosting-cards {
    /* Headroom so the "most popular" ribbon straddling the
       top of a card on the first row isn't clipped. */
    margin-top: 1.25rem;
}
/* With two product lines the full catalogue can spill onto a
   second row; the wider row gap keeps a second-row ribbon
   (straddling its card's top edge) out of the row above. */
.fi-hosting-cards.fi-fo-radio,
.fi-hosting-cards .fi-fo-radio {
    row-gap: 1.75rem;
}
.fi-hosting-cards .fi-fo-radio-label {
    position: relative;
    align-items: stretch;
    height: 100%;
    border: 1px solid color-mix(in oklab, var(--gray-950) 10%, transparent);
    border-radius: 0.75rem;
    padding: 1rem;
    cursor: pointer;
    transition: border-color 0.15s, background-color 0.15s;
}
.dark .fi-hosting-cards .fi-fo-radio-label {
    border-color: rgba(255, 255, 255, 0.1);
}
.fi-hosting-cards .fi-fo-radio-label:has(.fi-radio-input:checked) {
    border-color: var(--primary-600);
    background-color: color-mix(in oklab, var(--primary-500) 8%, transparent);
}
.fi-hosting-cards .fi-radio-input {
    position: absolute;
    top: 0.9rem;
    right: 0.9rem;
}
.fi-hosting-cards .fi-fo-radio-label-text {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.fi-hosting-cards .hosting-card-name {
    font-weight: 600;
    color: var(--gray-950);
}
.dark .fi-hosting-cards .hosting-card-name {
    color: var(--gray-50);
}
/* The "most popular" package is marked only by its ribbon
   label — no special border, so an unselected popular card
   looks like the others until you pick it. */
.fi-hosting-cards .hosting-card-popular {
    /* Straddles the card's top edge, half in / half out
       (centred on the edge regardless of its height). The
       card it sits on is the only one in its row, so the
       half that pokes out lands in the grid's top margin. */
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
    white-space: nowrap;
    border-radius: 9999px;
    padding: 0.15rem 0.7rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background-color: var(--primary-600);
    color: white;
}
/* Below Filament's md breakpoint the package grid stacks into
   a single column, so each card (except the first) now has a
   card directly above it. A ribbon straddling the top edge
   would hang in the gap and read as belonging to the card
   above, so tuck it fully inside its own card instead. */
@media (max-width: 47.99rem) {
    /* Ribbon headroom only where ribbons exist: the package picker —
       not the line/interval pairs, which have no ribbons to tuck. */
    .fi-hosting-cards:not(.fi-interval-cards):not(.fi-line-cards) .fi-fo-radio-label {
        padding-top: 1.9rem;
    }
    .fi-hosting-cards .hosting-card-popular,
    .fi-hosting-cards .hosting-card-current {
        top: 0.5rem;
        transform: translate(-50%, 0);
    }
}
/* Inside a MODAL the card grids stay single-column all the way up to
   lg (the grid breakpoints follow the viewport, but the modal is far
   narrower) — so the ribbon needs the same tucked-inside treatment up
   to that width there. */
@media (max-width: 63.99rem) {
    .fi-modal .fi-hosting-cards:not(.fi-interval-cards):not(.fi-line-cards) .fi-fo-radio-label {
        padding-top: 1.9rem;
    }
    .fi-modal .fi-hosting-cards .hosting-card-popular,
    .fi-modal .fi-hosting-cards .hosting-card-current {
        top: 0.5rem;
        transform: translate(-50%, 0);
    }
}
/* Prices and features stacked with consistent spacing. */
.fi-hosting-cards .fi-fo-radio-label-description {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
/* The headline price gets full contrast on every card so
   it reads clearly rather than inheriting the muted
   feature-text colour. */
.fi-hosting-cards .hosting-card-price {
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--gray-950);
}
.dark .fi-hosting-cards .hosting-card-price {
    color: var(--gray-50);
}
/* "per maand" stays intentionally secondary, but with an
   explicit muted colour so it reads the same on every card
   rather than inheriting each option's state colour. */
.fi-hosting-cards .hosting-card-subprice {
    font-size: 0.8rem;
    color: var(--gray-500);
}
.dark .fi-hosting-cards .hosting-card-subprice {
    color: var(--gray-400);
}
/* The yearly total and the saving badge on one line. */
.fi-hosting-cards .hosting-card-priceline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.15rem;
}
/* The yearly "Bespaar X%" badge shares the blue of the
   upgrade modal's "+€ X meer" pill, so savings and upgrades
   read as one accent rather than a stray green. */
.fi-hosting-cards .hosting-card-discount {
    border-radius: 9999px;
    padding: 0.1rem 0.5rem;
    font-size: 0.72rem;
    font-weight: 600;
    background-color: color-mix(in oklab, var(--primary-500) 16%, transparent);
    color: var(--primary-600);
}
.dark .fi-hosting-cards .hosting-card-discount {
    color: var(--primary-400);
}
/* Feature bullets at full contrast on every card, so a
   disabled (current) card reads as clearly as the rest. */
.fi-hosting-cards .hosting-card-feature {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    color: var(--gray-950);
}
.dark .fi-hosting-cards .hosting-card-feature {
    color: var(--gray-100);
}
/* A rule between the price block and what the package gives
   you, so a card reads as price-then-contents everywhere the
   cards appear — the pricing pages set a roomier version. */
.fi-hosting-cards .hosting-card-feature:first-of-type {
    margin-top: 0.35rem;
    padding-top: 0.65rem;
    border-top: 1px solid color-mix(in oklab, var(--gray-950) 10%, transparent);
}
.dark .fi-hosting-cards .hosting-card-feature:first-of-type {
    border-top-color: rgba(255, 255, 255, 0.08);
}
.fi-hosting-cards .hosting-card-feature::before {
    content: '✓';
    color: var(--primary-600);
    font-weight: 700;
}

/* Upgrade modal: the customer's current package is shown
   for comparison but can't be selected. It reads as muted
   and unclickable, with a neutral "Huidig pakket" badge in
   place of the popular ribbon. */
/* The current package is a reference to read, not a choice
   to make: mark it only by the badge and a faint neutral
   fill. Filament greys a disabled option's label to
   gray-400 and its description to gray-600 (near-invisible
   on the dark modal), so restore both to the same contrast
   as the selectable cards — the badge carries the "not an
   option" meaning, not unreadable text. */
.fi-hosting-cards .fi-fo-radio-label:has(.fi-radio-input:disabled) {
    cursor: default;
    background-color: color-mix(in oklab, var(--gray-500) 12%, transparent);
}
.fi-hosting-cards .fi-fo-radio-label:has(.fi-radio-input:disabled) .fi-radio-input {
    display: none;
}
.fi-hosting-cards .hosting-card-current {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
    white-space: nowrap;
    border-radius: 9999px;
    padding: 0.15rem 0.7rem;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background-color: var(--gray-200);
    color: var(--gray-700);
}
.dark .fi-hosting-cards .hosting-card-current {
    background-color: var(--gray-300);
    color: var(--gray-800);
}
/* The extra cost per term over the current package, on
   each selectable upgrade card. */
.fi-hosting-cards .hosting-card-diff {
    border-radius: 9999px;
    padding: 0.1rem 0.5rem;
    font-size: 0.72rem;
    font-weight: 600;
    background-color: color-mix(in oklab, var(--primary-500) 16%, transparent);
    color: var(--primary-600);
}
.dark .fi-hosting-cards .hosting-card-diff {
    color: var(--primary-400);
}

/* The billing-period picker reuses the card look but has no
   "most popular" ribbon, so it drops the headroom, sits a
   little tighter, and bolds its plain (non-HTML) label. */
.fi-hosting-cards.fi-interval-cards {
    margin-top: 0.75rem;
}
.fi-interval-cards .fi-fo-radio-label {
    padding: 0.75rem 0.9rem;
}
.fi-interval-cards .fi-fo-radio-label-text {
    font-weight: 600;
}
/* Its price is a supporting number, not the card's headline,
   so it stays a step below the package cards' price. */
.fi-interval-cards .hosting-card-price {
    font-size: 1.05rem;
}

/* The domain-search "basket" in the order-hosting modal
   (Order::renderDomainBasket): one cohesive component —
   a bordered pill (input + flush search button) with the
   results welded directly beneath it. Theme-adaptive
   tokens are defined once and flipped for dark mode, so
   every border/surface/text colour stays consistent. */
.chb-ds-wrap {
    font-size: 0.95rem;
    --chb-ds-border: color-mix(in oklab, var(--gray-950) 12%, transparent);
    --chb-ds-surface: var(--color-white);
    --chb-ds-seam: color-mix(in oklab, var(--gray-950) 8%, transparent);
    --chb-ds-row-border: color-mix(in oklab, var(--gray-950) 7%, transparent);
    --chb-ds-muted: color-mix(in oklab, var(--gray-950) 55%, transparent);
    --chb-ds-placeholder: color-mix(in oklab, var(--gray-950) 42%, transparent);
}
.dark .chb-ds-wrap {
    --chb-ds-border: rgba(255, 255, 255, 0.14);
    --chb-ds-surface: rgba(255, 255, 255, 0.03);
    --chb-ds-seam: rgba(0, 0, 0, 0.22);
    --chb-ds-row-border: rgba(255, 255, 255, 0.09);
    --chb-ds-muted: #d1d5db;
    --chb-ds-placeholder: rgba(255, 255, 255, 0.40);
}

/* Reusable theme-aware muted text for one-off inline labels:
   the readable grey in light mode, a brighter near-white in
   dark mode (the fixed --gray-500 was too dim to read). */
.chb-muted { color: var(--gray-500); }
.dark .chb-muted { color: #d1d5db; }

/* The "Hoofddomein" tag in the assigned-domains table: an
   outlined pill matching the subtle borders on the
   interval/package cards, rather than a filled amber badge.
   A calm slate-blue reads as "primary" without clashing with
   the tinted/gray Type badges next to it. */
.chb-primary-tag {
    display: inline-flex;
    align-items: center;
    margin-left: 0.45rem;
    padding: 0.05rem 0.5rem;
    border: 1px solid color-mix(in oklab, var(--primary-500) 45%, transparent);
    border-radius: 0.5rem;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.5rem;
    color: var(--primary-600);
    background: transparent;
}
.dark .chb-primary-tag {
    border-color: color-mix(in oklab, var(--primary-400) 55%, transparent);
    color: var(--primary-300);
}

/* A light-blue information callout (e.g. the "we do this by
   hand" notice in the move-to-own-package modal). */
.chb-info {
    display: flex;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-radius: 0.65rem;
    font-size: 0.85rem;
    line-height: 1.5;
    background-color: color-mix(in oklab, var(--primary-500) 12%, transparent);
    border: 1px solid color-mix(in oklab, var(--primary-500) 30%, transparent);
    color: var(--primary-700);
}
.dark .chb-info {
    color: var(--primary-200);
}
.chb-info svg {
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    margin-top: 0.05rem;
    color: var(--primary-600);
}
.dark .chb-info svg {
    color: var(--primary-300);
}

/* Give every content badge (status, Plesk sync, domain
   type, billing interval, invoice state …) the exact same
   clean look as the Hoofddomein tag: a crisp 1px border in
   the badge's own colour on a transparent fill, matched
   padding/radius/type — not Filament's chunkier, filled,
   soft-ring default. Scoped to .fi-main so the sidebar's
   cart-count badge stays filled and prominent; the customer
   panel only, so admin badges are untouched. */
.fi-main .fi-badge {
    padding-block: 0.05rem;
    padding-inline: 0.5rem;
    border-radius: 0.5rem;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.5rem;
    background-color: transparent;
    box-shadow: none;
    border: 1px solid color-mix(in oklab, var(--gray-600) 45%, transparent);
}
.fi-main .fi-badge:where(.dark, .dark *) {
    background-color: transparent;
    border-color: color-mix(in oklab, var(--gray-400) 55%, transparent);
}
.fi-main .fi-badge.fi-color {
    background-color: transparent;
    border-color: color-mix(in oklab, var(--color-600) 45%, transparent);
}
.fi-main .fi-badge.fi-color:where(.dark, .dark *) {
    background-color: transparent;
    border-color: color-mix(in oklab, var(--color-400) 55%, transparent);
}

/* The call-to-action button (review/check out): the primary
   brand blue, a touch darker on hover — one accent through the
   whole shop rather than a separate green for the money step. */
.chb-cta {
    background-color: var(--primary-600) !important;
    border-color: var(--primary-600) !important;
    color: #ffffff !important;
}
.chb-cta:hover {
    background-color: color-mix(in oklab, var(--primary-600) 80%, black) !important;
    border-color: color-mix(in oklab, var(--primary-600) 80%, black) !important;
    color: #ffffff !important;
}

/* The register-vs-own (and account-vs-elsewhere) toggle:
   a row of equal segmented buttons, the active one tinted. */
.chb-ds-modes {
    display: flex;
    gap: 0.6rem;
    margin-bottom: 1rem;
}
.chb-ds-modes--sub {
    margin-bottom: 0.9rem;
}
/* A second stacked input bar (e.g. the transfer auth-code row). */
.chb-ds-bar--spaced {
    margin-top: 0.5rem;
}
.chb-ds-mode {
    flex: 1 1 0;
    min-width: 0;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--chb-ds-border);
    border-radius: 0.6rem;
    background: transparent;
    color: inherit;
    font-size: 0.88rem;
    font-weight: 500;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.chb-ds-mode:hover {
    border-color: color-mix(in oklab, var(--primary-500) 45%, var(--chb-ds-border));
}
.chb-ds-mode--active {
    border-color: var(--primary-600);
    background: color-mix(in oklab, var(--primary-500) 12%, transparent);
}
.chb-ds-mode:focus-visible {
    outline: none;
    border-color: var(--primary-600);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--primary-500) 22%, transparent);
}

/* The pill bar: input + button share ONE bordered box. */
.chb-ds-bar {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--chb-ds-border);
    border-radius: 0.65rem;
    background: var(--chb-ds-surface);
    overflow: hidden;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
/* When results are attached, square the bar's bottom so
   the results surface welds to it. */
.chb-ds-bar--joined {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
/* Whole bar (input AND button) highlights together. */
.chb-ds-bar:focus-within {
    border-color: var(--primary-500);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--primary-500) 22%, transparent);
}
.chb-ds-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.65rem 0.85rem;
    border: none;
    outline: none;
    background: transparent;
    color: inherit;
    font-size: 0.95rem;
    line-height: 1.3;
}
.chb-ds-input::placeholder {
    color: var(--chb-ds-placeholder);
}
/* Flush, full-height button with a seam that tints on focus. */
.chb-ds-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 1.05rem;
    border: none;
    border-left: 1px solid var(--chb-ds-seam);
    background: var(--primary-600);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.chb-ds-bar:focus-within .chb-ds-btn {
    border-left-color: color-mix(in oklab, var(--primary-500) 60%, transparent);
}
.chb-ds-btn:hover {
    background: color-mix(in oklab, var(--primary-600) 80%, black);
}
.chb-ds-btn:disabled {
    cursor: not-allowed;
    opacity: 0.85;
}
.chb-ds-btn:focus-visible {
    outline: 2px solid #fff;
    outline-offset: -4px;
}
/* "Searching…" line — hidden until Livewire toggles it. */
.chb-ds-loading {
    display: none;
    align-items: center;
    gap: 0.45rem;
    margin: 0.55rem 0.15rem 0;
    font-size: 0.8rem;
    color: var(--chb-ds-muted);
}
.chb-ds-spinner {
    width: 0.85rem;
    height: 0.85rem;
    flex: 0 0 auto;
    border: 2px solid color-mix(in oklab, var(--primary-500) 35%, transparent);
    border-top-color: var(--primary-500);
    border-radius: 9999px;
    animation: chb-ds-spin 0.6s linear infinite;
}
@keyframes chb-ds-spin {
    to { transform: rotate(360deg); }
}
/* Results: one surface welded to the bar (no gap, shared border). */
.chb-ds-results {
    border: 1px solid var(--chb-ds-border);
    border-top: none;
    border-radius: 0 0 0.65rem 0.65rem;
    background: var(--chb-ds-surface);
    overflow: hidden;
}
/* A standalone bordered list (the account-domains picker). */
.chb-ds-panel {
    border: 1px solid var(--chb-ds-border);
    border-radius: 0.65rem;
    background: var(--chb-ds-surface);
    overflow: hidden;
}
/* Quick-add list of the order's other cart domains. */
.chb-ds-cartadd { margin: 0.9rem 0; }
.chb-ds-cartadd-label {
    font-size: 0.78rem;
    color: var(--chb-ds-muted);
    margin-bottom: 0.45rem;
}
.chb-ds-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.5rem 0.6rem 0.5rem 0.85rem;
    border: none;
    border-top: 1px solid var(--chb-ds-row-border);
    background: transparent;
    color: inherit;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s ease;
}
.chb-ds-row:first-child {
    border-top: none;
}
.chb-ds-row:hover {
    background: color-mix(in oklab, var(--primary-500) 9%, transparent);
}
.chb-ds-row:focus-visible {
    outline: none;
    background: color-mix(in oklab, var(--primary-500) 14%, transparent);
}
/* A non-actionable row (e.g. an unavailable domain): no
   hover/pointer, dimmed name. */
.chb-ds-row--muted {
    cursor: default;
}
.chb-ds-row--muted:hover {
    background: transparent;
}
.chb-ds-row--muted .chb-ds-row-name {
    color: var(--chb-ds-muted);
}
/* A non-clickable row whose name stays full-contrast (e.g.
   a taken-but-transferable domain showing its price). */
.chb-ds-row--static {
    cursor: default;
}
.chb-ds-row--static:hover {
    background: transparent;
}
/* "Transfer this taken domain to us" button on a taken row:
   a solid blue button with white text and the same
   darken-on-hover used everywhere else. */
.chb-ds-row-transfer {
    flex: 0 0 auto;
    padding: 0.35rem 0.85rem;
    border: none;
    border-radius: 0.5rem;
    background: var(--primary-600);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s ease;
}
.chb-ds-row-transfer:hover {
    background: color-mix(in oklab, var(--primary-600) 80%, black);
}
/* "Already in your cart" marker on a search result. The
   2.3rem min-height matches the cart-icon button so the
   row is the same height as the addable ones. */
.chb-ds-row-incart {
    flex: 0 0 auto;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    min-height: 2.3rem;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
    color: #00b67a;
}
/* The auth-code panel shown while transferring a domain in. */
.chb-ds-transfer {
    margin-top: 0.85rem;
    padding: 0.85rem;
    border: 1px solid var(--chb-ds-border);
    border-radius: 0.65rem;
    background: var(--chb-ds-surface);
}
.chb-ds-transfer-heading {
    margin: 0 0 0.6rem;
    font-size: 0.9rem;
    font-weight: 600;
}
.chb-ds-link {
    border: none;
    background: none;
    padding: 0;
    color: var(--primary-600);
    font-size: inherit;
    cursor: pointer;
    text-decoration: underline;
}
.dark .chb-ds-link {
    color: var(--primary-500);
}
/* Domain name on the left, taking the free space. */
.chb-ds-row-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}
/* The "+ Add" affordance on account-domain rows. */
.chb-ds-row-add {
    flex: 0 0 auto;
    margin-left: auto;
    color: var(--primary-600);
    font-weight: 600;
    font-size: 0.85rem;
    white-space: nowrap;
}
.dark .chb-ds-row-add {
    color: var(--primary-500);
}
/* Price (or "link" hint) pinned to the right, before the cart. */
.chb-ds-row-price {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: 0.85rem;
    color: var(--chb-ds-muted);
}
/* Blue cart button with a white icon. */
.chb-ds-cart {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.3rem;
    height: 2.3rem;
    border-radius: 0.6rem;
    background: var(--primary-600);
    color: #fff;
    transition: background 0.15s ease;
}
.chb-ds-row:hover .chb-ds-cart {
    background: var(--primary-500);
}
/* A clear, distinct background when pointing right at the
   cart button (wins over the row-hover shade above). */
.chb-ds-row .chb-ds-cart:hover {
    background: color-mix(in oklab, var(--primary-600) 80%, black);
}
.chb-ds-cart-icon {
    width: 1.25rem;
    height: 1.05rem;
}
.chb-ds-empty {
    margin: 0.55rem 0.15rem 0;
    font-size: 0.8rem;
    color: var(--chb-ds-muted);
}
/* Validation message under the "hosted elsewhere" input. */
.chb-ds-error {
    margin: 0.5rem 0.15rem 0;
    font-size: 0.8rem;
    color: #ef4444;
}
/* The selected-domains basket: a titled list of the domains
   added to this order. */
.chb-ds-basket {
    margin-top: 1rem;
}
/* Added domains, as a compact table: name (+ primary tag),
   what we'll do (register/link), and a remove button. */
.chb-ds-items {
    margin-top: 1rem;
    border: 1px solid var(--chb-ds-border);
    border-radius: 0.65rem;
    overflow: hidden;
}
/* Inside the titled basket the heading already supplies the
   gap, so the list sits flush under it. */
.chb-ds-basket .chb-ds-items {
    margin-top: 0;
}
.chb-ds-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.55rem 0.5rem 0.85rem;
    border-top: 1px solid var(--chb-ds-row-border);
}
.chb-ds-item:first-child {
    border-top: none;
}
.chb-ds-item-name {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    overflow: hidden;
    font-size: 0.9rem;
    font-weight: 500;
}
/* Long domain names ellipsize instead of clipping blind. */
.chb-ds-item-domain {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The "primary domain" pill next to the first name —
   a filled, higher-contrast badge (not a faint outline). */
.chb-ds-pill {
    flex: 0 0 auto;
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.14rem 0.55rem;
    border-radius: 9999px;
    color: var(--primary-600);
    background: color-mix(in oklab, var(--primary-500) 18%, transparent);
    border: none;
    white-space: nowrap;
}
.dark .chb-ds-pill {
    color: #fff;
    background: color-mix(in oklab, var(--primary-500) 42%, transparent);
}
/* "Make this the primary domain" star (non-primary rows). */
.chb-ds-item-star {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border: none;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--chb-ds-muted);
    opacity: 0.55;
    cursor: pointer;
    transition: opacity 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.chb-ds-item-star:hover {
    opacity: 1;
    color: var(--primary-600);
    background: color-mix(in oklab, var(--primary-500) 14%, transparent);
}
.dark .chb-ds-item-star:hover {
    color: #fff;
}
.chb-ds-star-icon {
    width: 1rem;
    height: 1rem;
}
.chb-ds-item-star-spacer {
    flex: 0 0 auto;
    width: 1.5rem;
}
/* What happens to this domain. */
.chb-ds-tag {
    flex: 0 0 auto;
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.2rem 0.55rem;
    border-radius: 9999px;
    white-space: nowrap;
}
/* Primary tint = we register it (a new, priced registration) —
   the same accent as the discount badge, so priced extras read
   as one family instead of a stray green. */
.chb-ds-tag--register {
    background: color-mix(in oklab, var(--primary-500) 16%, transparent);
    color: var(--primary-600);
}
.dark .chb-ds-tag--register {
    color: var(--primary-400);
}
/* Neutral = we link an existing domain (no charge). */
.chb-ds-tag--link {
    background: color-mix(in oklab, var(--gray-500) 14%, transparent);
    color: var(--chb-ds-muted);
}
.chb-ds-item-x {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border: none;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--chb-ds-muted);
    opacity: 0.7;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}
.chb-ds-item-x:hover {
    opacity: 1;
    background: color-mix(in oklab, var(--gray-500) 16%, transparent);
}
.chb-ds-note {
    margin-top: 0.85rem;
    font-size: 0.8rem;
    color: var(--chb-ds-muted);
}
/* Over the package's domain cap — must remove some to order. */
.chb-ds-warn {
    margin-top: 0.85rem;
    font-size: 0.82rem;
    font-weight: 500;
    color: #ef4444;
}
/* A basket domain already has hosting in the cart: warn and
   offer to replace it. */
.chb-ds-conflict {
    margin-top: 0.9rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid color-mix(in oklab, #f59e0b 45%, transparent);
    border-radius: 0.6rem;
    background: color-mix(in oklab, #f59e0b 12%, transparent);
}
.chb-ds-conflict-title {
    font-weight: 600;
    font-size: 0.85rem;
}
.chb-ds-conflict-body {
    margin-top: 0.15rem;
    font-size: 0.8rem;
    color: var(--chb-ds-muted);
}
.chb-ds-conflict-check {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    margin-top: 0.55rem;
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
}

/* Dashboard stat cards: centre the icon, label and figure.
   The content element is a grid, so this is justify-items
   rather than align-items. */
.fi-wi-stats-overview-stat-content {
    justify-items: center;
    text-align: center;
}
.fi-wi-stats-overview-stat-label-ctn {
    justify-content: center;
}
/* Outstanding invoices: neutral at zero, red as soon as
   there is something to pay. Filament's own dark rule for
   the figure is (0,2,0), so this is scoped one class
   deeper to win outright rather than on load order. */
.fi-wi-stats-overview-stat.chb-stat-alert .fi-wi-stats-overview-stat-value {
    color: var(--danger-400);
}

/* Dashboard widgets: the services / tickets / announcements
   lists share one row layout — a title-and-subtitle block on
   the left, status and actions on the right, collapsing to a
   stack on narrow screens. */
.chb-dash-list,
.chb-dash-empty {
    display: flex;
    flex-direction: column;
    /* Own muted token: the --chb-ds-* set is scoped to
       .chb-ds-wrap and is not in scope here. */
    --chb-dash-muted: color-mix(in oklab, var(--gray-950) 55%, transparent);
}
.dark .chb-dash-list,
.dark .chb-dash-empty {
    --chb-dash-muted: #d1d5db;
}
.chb-dash-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 0;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.chb-dash-row:first-child {
    border-top: 0;
    padding-top: 0;
}
.chb-dash-row:last-child {
    padding-bottom: 0;
}
.chb-dash-row-stacked {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
}
.chb-dash-row-main {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.chb-dash-row-title {
    font-weight: 600;
    font-size: 0.9rem;
}
.chb-dash-row-link {
    color: inherit;
}
.chb-dash-row-link:hover {
    color: var(--primary-400);
}
.chb-dash-row-sub {
    font-size: 0.8rem;
    color: var(--chb-dash-muted);
}
.chb-dash-row-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-shrink: 0;
}
.chb-dash-note {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    color: var(--chb-dash-muted);
}
.chb-dash-note-danger {
    color: var(--danger-400);
}
.chb-dash-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding: 1.75rem 0;
    text-align: center;
    font-size: 0.875rem;
    color: var(--chb-dash-muted);
}
/* The call to action under an empty card's message. */
.chb-dash-empty .fi-btn {
    margin-top: 0.5rem;
}
.chb-dash-empty-icon {
    width: 2.25rem;
    height: 2.25rem;
    opacity: 0.45;
    margin-bottom: 0.25rem;
}
.chb-dash-empty-hint {
    font-size: 0.8rem;
}

@media (max-width: 640px) {
    .chb-dash-row {
        flex-direction: column;
        align-items: flex-start;
    }
    .chb-dash-row-meta {
        width: 100%;
        justify-content: space-between;
    }
}

/* ---------------------------------------------------------------------------
   The extension price list, folded out under the shop's domain search.
   --------------------------------------------------------------------------- */
/* The fold-out toggle: a quiet text link with a chevron that rotates open,
   sitting right under the search help text so it reads as "there's more
   here" without competing with the search bar itself. */
.chb-prices-disclosure {
    margin-top: .9rem;
    padding-top: .9rem;
    border-top: 1px solid var(--gray-200);
}
.dark .chb-prices-disclosure {
    border-top-color: var(--gray-700);
}
.chb-prices-toggle {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--primary-600);
    cursor: pointer;
}
.dark .chb-prices-toggle {
    color: var(--primary-400);
}
.chb-prices-toggle:hover {
    text-decoration: underline;
}
.chb-prices-toggle-icon {
    width: .8rem;
    height: .8rem;
    transition: transform .15s ease;
}
.chb-prices-toggle-icon--open {
    transform: rotate(90deg);
}
.chb-prices-disclosure > div[x-show] {
    margin-top: .9rem;
}
.chb-prices-wrap {
    overflow-x: auto;
}
.chb-prices {
    width: 100%;
    border-collapse: collapse;
    font-size: .9rem;
}
.chb-prices th,
.chb-prices td {
    padding: .6rem .75rem;
    text-align: right;
    white-space: nowrap;
    border-bottom: 1px solid var(--gray-200);
}
.dark .chb-prices th,
.dark .chb-prices td {
    border-bottom-color: var(--gray-700);
}
/* The extension column reads as a label, so keep it left-aligned. */
.chb-prices th:first-child,
.chb-prices td:first-child {
    text-align: left;
}
.chb-prices thead th {
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    opacity: .65;
}
.chb-prices tbody tr:last-child th,
.chb-prices tbody tr:last-child td {
    border-bottom: 0;
}
.chb-prices-tld {
    font-weight: 600;
}
.chb-prices-muted {
    opacity: .55;
}
.chb-prices-note,
.chb-prices-empty {
    margin-top: .9rem;
    font-size: .82rem;
    opacity: .65;
}

/* The product-line pricing pages (Managed WordPress / WooCommerce
   hosting): the modal picker's cards, laid out as a standalone grid
   of links. The card box and its contents come from the
   .fi-hosting-cards rules above — this only adds the grid, the
   link reset and the per-card bestellen button. */
.chb-line-intro {
    max-width: 46rem;
    font-size: .9rem;
    opacity: .75;
}
.chb-line-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.25rem;
}
@media (min-width: 48rem) {
    .chb-line-cards {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
.chb-line-card {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    text-decoration: none;
}
.chb-line-card:hover {
    border-color: var(--primary-600);
}
/* Pricing-page hierarchy on top of the shared card styles: roomier
   cards, a big price line, a divider before the feature list, a
   hover lift, and a primary ring on the line's "populairst" card.
   Scoped to .chb-line-cards so the popup keeps its compact cards. */
.chb-line-cards .chb-line-card {
    padding: 1.5rem;
    border-radius: 1rem;
    transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.chb-line-cards .chb-line-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 14px 30px -18px rgba(0, 0, 0, 0.85);
}
.chb-line-cards .chb-line-card:has(.hosting-card-popular) {
    border-color: color-mix(in oklab, var(--primary-500) 55%, transparent);
}
.chb-line-cards .hosting-card-name {
    font-size: 1.05rem;
}
.chb-line-cards .hosting-card-price {
    margin-top: 0.4rem;
    font-size: 1.75rem;
    letter-spacing: -0.02em;
    line-height: 1.15;
}
.chb-line-cards .hosting-card-priceline {
    margin-bottom: 0.4rem;
}
.chb-line-cards .hosting-card-feature {
    font-size: 0.85rem;
    padding: 0.14rem 0;
}
/* Roomier than the shared rule above the feature list. */
.chb-line-cards .hosting-card-feature:first-of-type {
    margin-top: 0.55rem;
    padding-top: 1rem;
}
.chb-line-cards .chb-line-card-cta {
    padding-top: 0.65rem;
    padding-bottom: 0.65rem;
}

/* The bestellen button hugs the card's bottom edge, whatever the
   tallest card in the row is; the description above keeps clear of
   it. Styled by hand: Filament's .fi-btn rules don't dress a bare
   span, and the whole card is the actual link anyway. */
.chb-line-card .fi-fo-radio-label-description {
    margin-bottom: 1.25rem;
}
.chb-line-card-cta {
    margin-top: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.5rem;
    padding: 0.55rem 1rem;
    font-size: 0.875rem;
    font-weight: 600;
    background-color: var(--primary-600);
    color: white;
    transition: background-color 0.15s;
}
.chb-line-card:hover .chb-line-card-cta {
    background-color: color-mix(in oklab, var(--primary-600) 80%, black);
}

/* The Bestellen group header reads as a regular menu item — icon,
   full-contrast label, rounded hover — with the chevron as the fold
   affordance (Filament persists the fold state per browser). The
   portal's other groups are label-less, so this styles only that one. */
.fi-sidebar-group-btn {
    border-radius: 0.5rem;
    transition: background-color 75ms;
}
.fi-sidebar-group-btn:hover {
    background-color: color-mix(in oklab, var(--gray-950) 5%, transparent);
}
.dark .fi-sidebar-group-btn:hover {
    background-color: rgba(255, 255, 255, 0.05);
}
/* Match .fi-sidebar-item-label instead of the muted group default. */
.fi-sidebar-group-label {
    color: var(--gray-700);
}
.dark .fi-sidebar-group-label {
    color: var(--gray-200);
}
/* The label-less groups are one continuous menu with the Bestellen
   group sitting mid-list, so group seams get item spacing instead
   of Filament's wide section gap. */
.fi-sidebar-nav-groups {
    row-gap: 0.25rem;
}

/* The topbar language switcher: the current language's flag with a
   small caret, styled like the topbar's icon buttons; the dropdown
   options show flag + language name. */
.chb-lang {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    border-radius: 0.5rem;
    padding: 0.5rem;
    color: var(--gray-500);
    transition: background-color 75ms, color 75ms;
}
.dark .chb-lang {
    color: var(--gray-400);
}
.chb-lang:hover {
    background-color: color-mix(in oklab, var(--gray-950) 5%, transparent);
    color: var(--gray-700);
}
.dark .chb-lang:hover {
    background-color: rgba(255, 255, 255, 0.05);
    color: var(--gray-200);
}
.chb-lang-caret.fi-icon {
    width: 1rem;
    height: 1rem;
}
/* The flag itself: a small rounded rectangle; the SVG covers it
   (slice) so both flags render edge to edge. The faint inset ring
   keeps the white band of the Dutch flag visible on light ground. */
.chb-lang-flag {
    position: relative;
    display: inline-flex;
    width: 1.4rem;
    height: 1.05rem;
    border-radius: 0.25rem;
    overflow: hidden;
}
/* Painted ABOVE the SVG (an inset shadow on the container would
   render underneath it). */
.chb-lang-flag::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}
.dark .chb-lang-flag::after {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15);
}
.chb-lang-flag svg {
    width: 100%;
    height: 100%;
}
.chb-lang-option {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
/* The teleported panel: fixed to the viewport (positioned from the
   trigger by the switcher's own script), above the topbar's stacking
   context. */
.chb-lang-panel {
    position: fixed;
    z-index: 40;
    min-width: 0;
    width: max-content;
}
/* On the auth pages (simple layout, no topbar) the switcher sits as a
   right-aligned row at the top of the card, tucked toward its corner. */
.chb-lang-card {
    display: flex;
    justify-content: flex-end;
    margin: -0.75rem -0.75rem -1.25rem 0;
}
.chb-lang-check.fi-icon {
    width: 1rem;
    height: 1rem;
    margin-left: auto;
    color: var(--primary-400);
}
.chb-lang-panel .fi-dropdown-list-item {
    width: 100%;
}

/* The guest menu trigger rides Filament's own .fi-icon-btn (the bell's
   class), so it matches the topbar icons exactly; the signed-in avatar
   draws the same outlined user-circle at the same scale
   (User::getFilamentAvatarUrl). */
.chb-guest .fi-icon {
    width: 1.5rem;
    height: 1.5rem;
}
.chb-guest-item-icon.fi-icon {
    width: 1.15rem;
    height: 1.15rem;
    color: var(--gray-400);
}
