/* L-Mediehus Kundeportal — global styles.
 * Theme palette is defined in MainLayout.razor (MudTheme). This file MUST use
 * MudBlazor's CSS variables (--mud-palette-*) so colors react to dark mode.
 * NEVER hardcode hex colors here — use the palette variables.
 */

html, body {
    font-family: 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background-color: var(--mud-palette-background);
    color: var(--mud-palette-text-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1:focus, h2:focus, h3:focus, h4:focus, h5:focus, h6:focus {
    outline: none;
}

/* Validation utilities (kept from template — themed via palette) */
.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--mud-palette-success);
}

.invalid {
    outline: 1px solid var(--mud-palette-error);
}

.validation-message {
    color: var(--mud-palette-error);
}

/* Reconnect overlay styling now lives in scoped CSS:
 * Components/Layout/ReconnectModal.razor.css (ported from the .NET 10 template).
 * The modal is a native HTML <dialog> with ::backdrop — no global CSS needed. */

.blazor-error-boundary {
    background: var(--mud-palette-error);
    color: var(--mud-palette-error-contrast-text, #fff);
    padding: 1rem 1rem 1rem 3.7rem;
}

    .blazor-error-boundary::after {
        content: "Der opstod en uventet fejl.";
    }

/* ===== AppBar brand ===== */

.cp-brand-link {
    text-decoration: none;
    color: inherit;
}

/* L-Mediehus logo — sourced from CMS Backend wwwroot/images/favicon.svg.
 * Rounded for a polished feel; same asset works on both light blue
 * (#1E40AF) and dark slate (#0F172A) AppBars without filter tweaks.
 */
.cp-brand-logo {
    border-radius: 6px;
}

.cp-brand {
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--mud-palette-appbar-text);
}

/* ===== Drawer & navigation ===== */

.cp-drawer .mud-drawer-content {
    background-color: var(--mud-palette-drawer-background);
    border-right: 1px solid var(--mud-palette-divider);
}

.cp-nav-section-label {
    color: var(--mud-palette-text-secondary);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-size: 0.7rem;
    font-weight: 600;
}

.cp-nav-menu .mud-nav-link {
    margin: 2px 8px;
    border-radius: 8px;
    color: var(--mud-palette-drawer-text);
    transition: background-color 120ms ease-in-out, color 120ms ease-in-out;
}

    .cp-nav-menu .mud-nav-link .mud-icon-root {
        color: var(--mud-palette-drawer-icon);
    }

    .cp-nav-menu .mud-nav-link.active {
        background-color: var(--mud-palette-primary-hover);
        color: var(--mud-palette-primary);
        font-weight: 600;
    }

        .cp-nav-menu .mud-nav-link.active .mud-icon-root {
            color: var(--mud-palette-primary);
        }

    .cp-nav-menu .mud-nav-link:hover:not(.active) {
        background-color: var(--mud-palette-action-default-hover);
    }

/* ===== Sidebar shell (ChatGPT-style: header / scrollable nav / account footer) =====
 * There is no desktop app bar — the brand lives at the top of the drawer and the account
 * button at the bottom. .mud-drawer-content is already display:flex; flex-direction:column;
 * height:100%, so header/footer are flex:0 0 auto and the nav region flexes + scrolls.
 */

.cp-drawer-header {
    flex: 0 0 auto;
    padding: 16px 16px 12px;
    border-bottom: 1px solid var(--mud-palette-divider);
}

/* Brand text defaults to appbar-text (white) for the mobile app bar; inside the white sidebar
   header it must use primary text instead. */
.cp-drawer-header .cp-brand {
    color: var(--mud-palette-text-primary);
}

.cp-drawer-nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.cp-drawer-footer {
    flex: 0 0 auto;
    border-top: 1px solid var(--mud-palette-divider);
    padding: 8px;
}

/* Token-usage chip centered as a pill in the sidebar footer. Flex-center the container so the
   chip (wrapped in a MudTooltip span) sits in the middle regardless of its content width. */
.cp-drawer-footer-tokens {
    display: flex;
    justify-content: center;
    padding: 4px 4px 8px;
    position: relative;
    z-index: 31; /* above the popout (z-index 30) once lifted */
    transition: transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* When the account popout opens, slide the token chip up above it so it isn't covered.
   --cp-popout-h is measured live by account-menu.js; the fallback keeps it close before JS runs. */
.cp-drawer-footer-tokens--lifted {
    transform: translateY(calc(-1 * (var(--cp-popout-h, 205px) + 12px)));
}

    .cp-drawer-footer-tokens .cp-token-chip {
        margin: 0;
    }

/* Full-width account activator — avatar + name, opens the account popout upward. */
.cp-account-activator {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: 10px;
    cursor: pointer;
    transition: background-color 120ms ease-in-out;
}

    .cp-account-activator:hover {
        background-color: var(--mud-palette-action-default-hover);
    }

/* Name (over) + company (under), stacked. min-width:0 lets both lines ellipsis-truncate. */
.cp-account-meta {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.cp-account-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.cp-account-company {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
}

/* ===== Main content ===== */

/* Soft, professional backdrop — faint brand-blue + cyan radial washes over the light base,
   instead of a flat near-white fill. background-attachment: fixed keeps the wash anchored to
   the viewport so it reads as ambient lighting rather than a tiling pattern as content scrolls.
   Tints are very low alpha (≤6%) so cards/text on top keep full contrast. */
.cp-main-content {
    min-height: 100vh;
    background-color: var(--mud-palette-background);
    background-image:
        radial-gradient(900px circle at 0% 0%, rgba(30, 64, 175, 0.06), transparent 55%),
        radial-gradient(1100px circle at 100% 8%, rgba(8, 145, 178, 0.05), transparent 50%),
        linear-gradient(180deg, rgba(241, 245, 249, 0.6) 0%, transparent 320px);
    background-attachment: fixed, fixed, scroll;
    background-repeat: no-repeat;
}

/* MudMainContent always reserves AppbarHeight of top padding. On desktop there is no app bar,
   so kill the phantom gap. Scoped to >= Md: below it the mobile app bar is present and the
   offset is wanted. 960px is MudBlazor's Md breakpoint. */
@media (min-width: 960px) {
    .cp-main-content {
        padding-top: 0 !important;
    }
}

/* ===== Navigation progress bar (top of viewport) ===== */

.cp-nav-progress {
    position: fixed !important;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2000;
    height: 3px !important;
}

/* ===== Breadcrumbs ===== */

.cp-breadcrumbs {
    background-color: transparent;
}

.cp-breadcrumbs .mud-breadcrumbs-item .mud-breadcrumbs-text {
    color: var(--mud-palette-text-secondary);
    font-size: 0.85rem;
}

.cp-breadcrumbs .mud-breadcrumbs-item:last-child .mud-breadcrumbs-text {
    color: var(--mud-palette-primary);
    font-weight: 500;
}

.cp-breadcrumbs .mud-breadcrumbs-separator {
    color: var(--mud-palette-text-disabled);
}

/* ===== Password field with leading lock icon =====
 * MudTextField only supports one adornment position, so the show/hide eye lives on
 * Adornment.End and we paint a lock SVG at the start via a pseudo-element. The icon
 * is decorative only (pointer-events: none) so the input remains fully clickable.
 */

.cp-input-with-lock .mud-input {
    position: relative;
}

    .cp-input-with-lock .mud-input::before {
        content: '';
        position: absolute;
        left: 14px;
        top: 50%;
        transform: translateY(-50%);
        width: 20px;
        height: 20px;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%236B7280' d='M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM9 6c0-1.66 1.34-3 3-3s3 1.34 3 3v2H9V6zm9 14H6V10h12v10zm-6-3c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: center;
        background-size: contain;
        z-index: 2;
        pointer-events: none;
        opacity: 0.7;
    }

.cp-input-with-lock .mud-input-slot {
    padding-left: 44px !important;
}

/* ===== Cards & surfaces ===== */

.cp-card {
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 12px;
}

.cp-empty-state {
    border: 1px dashed var(--mud-palette-lines-default) !important;
    border-radius: 16px !important;
    background-color: var(--mud-palette-surface);
}

.cp-campaign-card {
    transition: transform 120ms ease-in-out, box-shadow 120ms ease-in-out;
    background-color: var(--mud-palette-surface);
    /* Clip the full-bleed preview band's top corners to the card's radius. */
    overflow: hidden;
}

    .cp-campaign-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
    }

.cp-campaign-title {
    line-height: 1.3;
    word-break: break-word;
}

.cp-campaign-desc {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Campaign-card banner filmstrip — up to 3 latest ads previewed at the top of each
   campaign card. The whole band is pointer-events:none so a click on any banner falls
   through to the card's @onclick (→ campaign detail); the banners are visuals only. */
.cp-campaign-preview {
    display: flex;
    gap: 6px;
    padding: 8px;
    height: 150px;
    background-color: var(--mud-palette-background-gray);
    border-bottom: 1px solid var(--mud-palette-divider);
    position: relative;
    pointer-events: none;
}

.cp-campaign-preview-tile {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--mud-palette-surface);
    border-radius: 6px;
    overflow: hidden;
}

.cp-campaign-preview-empty {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    color: var(--mud-palette-text-secondary);
}

.cp-campaign-preview-more {
    position: absolute;
    bottom: 8px;
    right: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    background-color: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-size: 0.75rem;
    line-height: 1.4;
    font-weight: 600;
}

.cp-dropzone {
    border: 2px dashed var(--mud-palette-lines-default) !important;
    border-radius: 12px !important;
    background-color: var(--mud-palette-surface);
    transition: border-color 120ms ease-in-out, background-color 120ms ease-in-out;
    cursor: pointer;
}

    .cp-dropzone:hover {
        border-color: var(--mud-palette-primary) !important;
        background-color: var(--mud-palette-action-default-hover);
    }

    /* Active drag state — set by JS interop in file-upload.js while a file hovers over the zone. */
    .cp-dropzone.drop-zone-active {
        border-color: var(--mud-palette-primary) !important;
        background-color: var(--mud-palette-primary-hover) !important;
    }

/* Staged-file row: thumbnail + name/info + delete. Tight gap so the X sits next
 * to the info instead of edge-aligned. */
.cp-file-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    border-radius: 8px;
    transition: background-color 120ms ease-in-out;
}

/* Large variant — scoped to whatever container opts in via .cp-file-list--lg. Used on the
   AdRequest detail page where the right column is wide enough that the default 48×48 thumbs
   look lost. Bumps the thumb to 88×88 + scales the surrounding padding/typography to match. */
.cp-file-list--lg .cp-file-row {
    padding: 14px 16px;
    gap: 16px;
}

.cp-file-list--lg .cp-file-thumb {
    width: 88px;
    height: 88px;
    min-width: 88px;
    border-radius: 10px;
}

    .cp-file-list--lg .cp-file-thumb .mud-icon-root {
        font-size: 2.2rem;
    }

    /* Show the whole reference image rather than a cropped square — for a "what did I upload?"
       list, seeing the full content beats a uniform composition. Same Photoshop-style
       checkerboard the AssetPreviewDialog uses, scaled down to 10px tiles since the thumb is
       only 88×88. Opaque images cover it completely; transparent PNGs show the standard
       transparency-indicator both behind alpha pixels and in the letterbox bars. */
    .cp-file-list--lg .cp-file-thumb img {
        object-fit: contain;
        background-color: #ffffff;
        background-image:
            linear-gradient(45deg, #d4d4d4 25%, transparent 25%),
            linear-gradient(-45deg, #d4d4d4 25%, transparent 25%),
            linear-gradient(45deg, transparent 75%, #d4d4d4 75%),
            linear-gradient(-45deg, transparent 75%, #d4d4d4 75%);
        background-size: 10px 10px;
        background-position: 0 0, 0 5px, 5px -5px, 5px 0;
    }

.cp-file-list--lg .cp-file-info .cp-file-name {
    font-size: 1rem;
}

.cp-file-list--lg .cp-file-info .mud-typography-caption {
    font-size: 0.85rem;
}

    .cp-file-row + .cp-file-row {
        margin-top: 4px;
    }

    .cp-file-row:hover {
        background-color: var(--mud-palette-action-default-hover);
    }

.cp-file-thumb {
    width: 48px;
    height: 48px;
    min-width: 48px;
    border-radius: 8px;
    background-color: var(--mud-palette-background-gray);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
    border: 1px solid var(--mud-palette-lines-default);
}

    .cp-file-thumb img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

/* Video thumbnail: first frame via #t=0.5 with a centered play overlay. */
.cp-file-thumb-video {
    position: relative;
    width: 100%;
    height: 100%;
}

    .cp-file-thumb-video video {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
        background: #000;
    }

.cp-file-thumb-play {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

    .cp-file-thumb-play .mud-icon-root {
        color: #fff;
        background: rgba(0, 0, 0, 0.55);
        border-radius: 50%;
        padding: 2px;
        width: 22px;
        height: 22px;
        font-size: 18px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    }

.cp-file-info {
    flex: 1 1 auto;
    min-width: 0; /* allow text-overflow inside flex child */
    overflow: hidden;
}

    .cp-file-info .cp-file-name {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

.cp-file-warning {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
    cursor: help;
}

.cp-file-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
}

/* Preview dialog body — neutral surface so transparent/white images are visible and
   media of any aspect ratio centers cleanly. */
.cp-asset-preview-body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 320px;
    max-height: 78vh;
    overflow: auto;
    padding: 12px;
    background-color: var(--mud-palette-background-grey);
    border-radius: 8px;
}

/* Photoshop-style checkerboard applied directly to the <img>. Opaque images cover
   it completely (JPGs etc. look unchanged); PNGs with alpha — including pure-white
   logos — get the standard transparency-indicator behind them, so the content is
   always visible against the dialog. */
.cp-asset-preview-img {
    max-width: 100%;
    max-height: calc(78vh - 24px);
    display: block;
    object-fit: contain;
    border-radius: 4px;
    background-color: #ffffff;
    background-image:
        linear-gradient(45deg, #d4d4d4 25%, transparent 25%),
        linear-gradient(-45deg, #d4d4d4 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #d4d4d4 75%),
        linear-gradient(-45deg, transparent 75%, #d4d4d4 75%);
    background-size: 20px 20px;
    background-position: 0 0, 0 10px, 10px -10px, 10px 0;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.cp-asset-preview-video {
    max-width: 100%;
    max-height: calc(78vh - 24px);
    display: block;
    border-radius: 4px;
    background-color: #000;
}

.cp-asset-preview-audio {
    width: min(100%, 480px);
    display: block;
}

.cp-asset-preview-pdf {
    width: 100%;
    height: 78vh;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    display: block;
    background-color: #ffffff;
}

.cp-ad-request-shelf {
    background-color: var(--mud-palette-background-gray);
    border-radius: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

/* Clickable header on the request shelf — opens the AdRequest detail page. Only the title
   block is the hit-target; the action icons sit outside this element so they don't double-fire. */
.cp-ad-request-shelf-head {
    cursor: pointer;
    flex: 1 1 auto;
    min-width: 0;
    border-radius: 6px;
    transition: background-color 120ms ease-in-out;
}

    .cp-ad-request-shelf-head:hover {
        background-color: rgba(0, 0, 0, 0.03);
    }

/* Color swatch chip on the AdRequest detail page. */
.cp-color-swatch {
    width: 20px;
    height: 20px;
    border-radius: 4px;
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}

/* Reference-file tile on the AdRequest detail page. Image fills the tile; videos show a placeholder
   icon; the caption is a small description below. The link covers the thumb so click-to-open works. */
.cp-reference-tile {
    overflow: hidden;
    background-color: var(--mud-palette-background-gray);
}

.cp-reference-tile-link {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
}

.cp-reference-tile-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cp-reference-tile-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-text-secondary);
}

.cp-reference-tile-caption {
    display: block;
    padding: 4px 8px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cp-banner-card {
    transition: box-shadow 120ms ease-in-out, transform 120ms ease-in-out;
    background-color: var(--mud-palette-surface);
    border-radius: 10px;
    border-top: 3px solid var(--mud-palette-lines-default);
    overflow: hidden;
}

    .cp-banner-card:hover {
        box-shadow: 0 8px 22px rgba(0, 0, 0, 0.10);
        transform: translateY(-1px);
    }

.cp-banner-card--html5     { border-top-color: var(--mud-palette-primary); }
.cp-banner-card--newspaper { border-top-color: var(--mud-palette-secondary); }
.cp-banner-card--image     { border-top-color: var(--mud-palette-info); }
.cp-banner-card--video     { border-top-color: var(--mud-palette-warning); }
.cp-banner-card--audio     { border-top-color: var(--mud-palette-tertiary); }

.cp-banner-thumb {
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    overflow: hidden;
    position: relative;
    margin: 0 auto;
}

.cp-banner-thumb-audio {
    width: 100%;
    max-width: 100%;
    display: block;
    margin: auto;
}

.cp-banner-thumb-img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
    margin: auto;
}

.cp-banner-thumb-iframe-scaled {
    display: block;
    width: var(--preview-width, 100%);
    height: var(--preview-height, 100%);
    border: 0;
    background: #ffffff;
    transform: scale(var(--preview-scale, 1));
    transform-origin: top left;
    pointer-events: none;
}

@supports (zoom: 1) {
    .cp-banner-thumb-iframe-scaled {
        transform: none;
        zoom: var(--preview-scale, 1);
    }
}

.cp-banner-thumb-pdf {
    width: 100%;
    height: 100%;
    border: 0;
    background: #ffffff;
}

.cp-banner-thumb-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Annoncer grid — fits as many cards per row as the container allows, capped
   at ~360px per card so banner thumbs aren't surrounded by huge whitespace on
   2K/4K monitors. Rows are horizontally centered so a partial bottom row
   doesn't look left-orphaned. Falls back to a single column on mobile. */
.cp-banner-grid {
    display: grid;
    /* auto-fit so empty tracks collapse — with one card you get one track,
       no phantom slots padding the row. */
    grid-template-columns: repeat(auto-fit, minmax(280px, 360px));
    gap: 16px;
    justify-content: start;
    align-items: start;
}

@media (max-width: 600px) {
    .cp-banner-grid {
        grid-template-columns: 1fr;
    }
}

/* Banner card header on campaign detail — 3-column grid keeps the title truly
   centered: approved checkmark sits flush left, the actions menu flush right. */
.cp-banner-card-header {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 8px;
    min-height: 28px;
}

    .cp-banner-card-title {
        grid-column: 2;
        text-align: center;
    }

    .cp-banner-card-approved {
        grid-column: 1;
        justify-self: start;
        display: inline-flex;
        align-items: center;
    }

    .cp-banner-card-menu {
        grid-column: 3;
        justify-self: end;
        display: inline-flex;
        align-items: center;
    }

    /* Any other header child (e.g. AdItem's ad-kind label on the /annoncer list) sits flush right,
       except the approved checkmark which is pinned left above. */
    .cp-banner-card-header > :not(.cp-banner-card-title):not(.cp-banner-card-approved) {
        grid-column: 3;
        justify-self: end;
    }

/* Centered ad-kind + source badge row under the card header. */
.cp-banner-card-kindrow {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

/* Drag-and-drop PDF upload zone (Upload PDF-annonce dialog). The native <input type="file"> is
   overlaid transparently so click-to-browse and native drag-drop both work; the wrapper only
   toggles .is-dragging for the highlight. */
.cp-pdf-dropzone {
    position: relative;
    border: 2px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    background-color: var(--mud-palette-background-gray);
    padding: 28px 16px;
    text-align: center;
    transition: border-color 120ms ease, background-color 120ms ease;
}

    .cp-pdf-dropzone.is-dragging {
        border-color: var(--mud-palette-primary);
        background-color: var(--mud-palette-primary-hover);
    }

.cp-pdf-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.cp-pdf-dropzone-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

/* Compact ad-kind label in the top-right of an AdItem card. */
.cp-ad-type-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1;
}

/* Banner card action row on the campaign detail page — buttons always stack
   one per row at full width, on all screen sizes. The thumb is capped at
   ~360px so a full-width button under it stays readable; side-by-side buttons
   in a narrow card looked cramped. */
.cp-banner-actions {
    flex-direction: column !important;
    align-items: stretch !important;
}

    .cp-banner-actions .mud-button-root {
        width: 100%;
    }

/* AdItem card action row — four small buttons (Vis · Ret · download · Slet)
   share the row equally, wrapping on tight widths. The download entry can
   be either a single button or a split-button (main + caret menu).
   On phones (≤600px) the row drops to 2-up: Vis + Ret, then download + Slet. */
.cp-ad-actions {
    flex-wrap: wrap;
    align-items: stretch !important;
}

    .cp-ad-actions > .cp-ad-action {
        flex: 1 1 0;
        min-width: 0;
    }

@media (max-width: 599.95px) {
    .cp-ad-actions > .cp-ad-action {
        /* flex-basis = (row width − Spacing=1 gap) ÷ 2, so exactly two fit per row. */
        flex: 1 1 calc(50% - 2px);
    }
}

    .cp-ad-actions .mud-button-root {
        min-width: 0;
        padding-left: 6px;
        padding-right: 6px;
    }

        .cp-ad-actions .mud-button-root .mud-button-label {
            font-size: 0.75rem;
            line-height: 1;
        }

        .cp-ad-actions .mud-button-root .mud-button-icon-start {
            margin-right: 4px;
            margin-left: 0;
        }

/* Split-button: main MudButton on the left + MudMenu (built-in IconButton activator) on the
   right. The two share a single rounded outline by zeroing the inner corners on each side and
   bolting them together with a faint divider. The cp-ad-split-toggle class lands on MudMenu's
   wrapper div — keep that wrapper flush (no padding/margin) and push all the visual styling
   (border-radius, border-left, padding) onto the inner button itself. Otherwise the wrapper's
   own padding shows up as a visible gap between the two halves. */
.cp-ad-split {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    min-height: 0;
}

    .cp-ad-split .cp-ad-split-main {
        flex: 1 1 auto;
        min-width: 0;
        margin: 0 !important;
    }

    /* Only strip the main button's right radius when a toggle is actually present. Audio ads
       have no alternative formats so the toggle isn't rendered; the main button is then a
       standalone button and should keep its full pill shape. :has() selects parents-by-child. */
    .cp-ad-split:has(.cp-ad-split-toggle) .cp-ad-split-main {
        border-top-right-radius: 0 !important;
        border-bottom-right-radius: 0 !important;
    }

    /* MudMenu's outer wrapper (cp-ad-split-toggle class lands here). MUST stay flush — any
       padding or margin here is the gap the user sees. Also has to stretch vertically so its
       child icon-button can fill the row's height. */
    .cp-ad-split .cp-ad-split-toggle {
        display: inline-flex;
        align-items: stretch;
        align-self: stretch;
        padding: 0 !important;
        margin: 0 !important;
        background: transparent !important;
        border: none !important;
    }

        /* MudIconButton that MudMenu renders as its activator. Force height: 100% — MudIconButton
           is content-sized at Size.Small (~28px) and would otherwise read shorter than the main
           MudButton (~30px); explicit 100% lets the flex stretch chain reach the icon. */
        .cp-ad-split .cp-ad-split-toggle > .mud-button-root,
        .cp-ad-split .cp-ad-split-toggle > button {
            border-top-left-radius: 0 !important;
            border-bottom-left-radius: 0 !important;
            border-left: 1px solid rgba(255, 255, 255, 0.35) !important;
            min-width: 30px;
            height: 100% !important;
            align-self: stretch;
            padding: 0 4px !important;
            margin: 0 !important;
        }

.cp-ad-split-menu .mud-list-item {
    font-size: 0.8rem;
}

.cp-section-card {
    height: 100%;
}

/* ===== Generate-ad page (/annoncer/ny) ===== */

/* Row of five large kind tiles (HTML5, Avis, Billede, Video, Lyd). Three are active, two are
   disabled with tooltip — the disabled state must be visibly distinct. */
.cp-generator-kind-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
}

.cp-generator-kind-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 16px;
    border: 1.5px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background-color: var(--mud-palette-surface);
    transition: border-color 120ms ease-in-out, box-shadow 120ms ease-in-out, transform 120ms ease-in-out;
    cursor: pointer;
    user-select: none;
    text-align: center;
    outline: none;
}

    .cp-generator-kind-card:hover:not(.is-disabled):not(.is-selected) {
        border-color: var(--mud-palette-primary-darken);
        transform: translateY(-1px);
        box-shadow: 0 4px 14px rgba(0, 0, 0, 0.05);
    }

    .cp-generator-kind-card:focus-visible {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }

    .cp-generator-kind-card.is-selected {
        border-color: var(--mud-palette-primary);
        border-width: 2px;
        background-color: rgba(var(--mud-palette-primary-rgb), 0.06);
        box-shadow: 0 4px 14px rgba(0, 0, 0, 0.05);
    }

    .cp-generator-kind-card.is-disabled {
        opacity: 0.45;
        cursor: not-allowed;
        background-color: var(--mud-palette-background-gray);
    }

/* Format multi-select cards (FormatType / NewspaperAdFormat / ImageAdFormat). Each shows an
   aspect-ratio preview box so the user can see relative proportions at a glance. */
.cp-generator-format-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px;
    padding: 8px 0;
}

.cp-generator-format-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 12px;
    border: 1.5px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background-color: var(--mud-palette-surface);
    cursor: pointer;
    transition: border-color 120ms ease-in-out, transform 120ms ease-in-out;
    outline: none;
    text-align: center;
}

    .cp-generator-format-card:hover:not(.is-selected) {
        border-color: var(--mud-palette-primary-darken);
        transform: translateY(-1px);
    }

    .cp-generator-format-card:focus-visible {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }

    .cp-generator-format-card.is-selected {
        border-color: var(--mud-palette-primary);
        border-width: 2px;
        background-color: rgba(var(--mud-palette-primary-rgb), 0.06);
    }

.cp-generator-format-preview {
    background-color: var(--mud-palette-background-gray);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    min-width: 8px;
    min-height: 8px;
}

.cp-generator-newspaper-panels {
    margin-top: 4px;
}

/* Color palette rows */
.cp-generator-color-row {
    padding: 6px 8px;
    border-radius: 6px;
    background-color: var(--mud-palette-background-gray);
}

.cp-generator-color-swatch {
    width: 36px;
    height: 36px;
    border-radius: 6px;
    border: 1px solid var(--mud-palette-lines-default);
    padding: 0;
    cursor: pointer;
    background-color: transparent;
}

/* Overlay text rows */
.cp-generator-overlay-row {
    background-color: var(--mud-palette-background);
}

/* Live font preview inside the overlay-text textarea. The row sets --cp-overlay-font from its
   selected font; this rule pushes it onto the inner MudBlazor textarea. !important is needed
   because MudBlazor's own .mud-input-slot rule sets font-family on the same element and would
   otherwise win the cascade against an inline style. */
.cp-generator-overlay-row .mud-input-slot {
    font-family: var(--cp-overlay-font), sans-serif !important;
    font-size: 1.05rem;
}

.cp-generator-overlay-preview {
    font-size: 22px;
    line-height: 1.2;
    color: var(--mud-palette-text-primary);
}

/* Media upload */
.cp-generator-media-dropzone {
    border: 2px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    transition: border-color 120ms ease-in-out, background-color 120ms ease-in-out;
}

    .cp-generator-media-dropzone:hover {
        border-color: var(--mud-palette-primary);
        background-color: rgba(var(--mud-palette-primary-rgb), 0.03);
    }

.cp-generator-media-row {
    background-color: var(--mud-palette-background);
}

.cp-generator-media-thumb {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-background-gray);
}

/* Wrapper around the thumb+badge — clickable target for the preview dialog. inline-block so
   the wrapper hugs the 56px thumb (otherwise it'd stretch to the row width, throwing off the
   badge's horizontal centering). */
.cp-generator-media-thumb-wrap {
    position: relative;
    display: inline-block;
    cursor: pointer;
    outline: none;
}

    .cp-generator-media-thumb-wrap:hover .cp-generator-media-thumb {
        border-color: var(--mud-palette-primary);
    }

    .cp-generator-media-thumb-wrap:focus-visible {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
        border-radius: 6px;
    }

/* "Media #N" badge — small chip centered below the thumb so the user can see how to reference
   the file in their AI instructions ("Brug Media #1 som baggrund"). */
.cp-generator-media-badge {
    position: absolute;
    bottom: -10px;
    left: 50%;
    transform: translateX(-50%);
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    padding: 2px 6px;
    border-radius: 10px;
    line-height: 1.2;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
    pointer-events: none;
    white-space: nowrap;
}

.cp-generator-summary {
    position: sticky;
    top: 10px;
}

/* Scrollable results column inside the post-Generate side-panel. Caps height so a 10-ad run
   doesn't push the page; user scrolls inside the column while the form stays visible left. */
.cp-generator-results {
    max-height: calc(100vh - 280px);
    overflow-y: auto;
    padding: 4px;
}

/* Status line on the active (currently-generating) skeleton. Matches the placeholder header height so
   the card doesn't jump when the spinner+status swaps in for the skeleton bars. */
.cp-skeleton-status {
    min-height: 20px;
}

/* Subtle separator between generation batches in the results column — just enough to read the grouping
   (newest batch on top) without competing with the cards themselves. */
.cp-batch-divider {
    margin: 2px 0;
    opacity: 0.5;
}

/* Font picker options — render each option in its own typeface so the user previews the font
   before picking (Word-style). Slightly bigger than the surrounding MudSelectItem text so the
   character shapes are recognisable at a glance. */
.cp-generator-font-option {
    font-size: 1.05rem;
    line-height: 1.4;
    display: inline-block;
}

/* Hero number ("23 annoncer klar til generering") above the breakdown tiles */
.cp-generator-hero {
    text-align: center;
    padding: 8px 0;
    border-bottom: 1px solid var(--mud-palette-divider-light);
}

.cp-generator-hero-number {
    font-size: 2.8rem;
    line-height: 1.0;
    font-weight: 700;
    color: var(--mud-palette-primary);
    letter-spacing: -0.02em;
}

/* Single stat row in the Status panel — icon | label (flex-grow) | value (right) */
.cp-generator-stat-tile {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}

.cp-generator-stat-label {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.cp-generator-stat-value {
    font-size: 1rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

/* Newspaper clickable-canvas selector — image + absolutely-positioned canvas overlay */
.cp-newspaper-canvas {
    display: flex;
    justify-content: center;
    padding: 12px 0;
}

.cp-newspaper-image-container {
    position: relative;
    display: inline-block;
    max-width: 100%;
}

    .cp-newspaper-image-container img {
        display: block;
        max-width: 100%;
        height: auto;
        user-select: none;
        -webkit-user-drag: none;
    }

.cp-newspaper-canvas-overlay {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: auto;
}

/* Overlay-text preview box (issue #1) — dashed-border, 22px font, sits below the inputs */
.cp-generator-overlay-preview-box {
    border-radius: 6px;
    border: 1px dashed var(--mud-palette-lines-default);
    background-color: var(--mud-palette-background-gray);
    padding: 14px 16px;
    font-size: 22px;
    line-height: 1.3;
    color: var(--mud-palette-text-primary);
    white-space: pre-line;
    min-height: 56px;
}

/* ===== Edit-ad page (/rediger-annonce/{id}) =====
   Padding scale: panel internals 16px, toolbar 12×16, internal section gaps 12px. Match the
   chat-side and preview-side panes so the two columns feel like a single editor.

   Height strategy: both columns stretch to the same viewport-derived height via the grid.
   The right column's toolbar takes whatever it needs at the top, the preview pane flexes
   to fill the remainder, so its bottom edge naturally aligns with the chat pane below. */

.cp-editor-shell {
    align-items: stretch;
    min-height: calc(100vh - 190px);
}

/* Desktop: bind the editor to the viewport so each column is a fixed-height region whose INNER
   content scrolls (the chat log, the Monaco "Kode" host, the preview) — NOT the whole shell. Without
   this the shell only had a min-height, so the chat log and code editor collapsed/over-grew. Key
   details: the shell is clipped (overflow:hidden, never a scroll container of its own); nowrap + an
   explicit 100% item height stop the taller preview column from inflating the row and dragging the
   chat column past the viewport. Mobile (stacked columns) keeps the natural min-height flow. */
@media (min-width: 960px) {
    .cp-editor-shell {
        height: calc(100vh - 180px);
        flex-wrap: nowrap;
        overflow: hidden;
    }

    .cp-editor-shell > .mud-grid-item {
        height: 100%;
        max-height: 100%;
    }

    .cp-editor-pane--chat {
        min-height: 0;
    }

    /* If a tall preview overflows its column, scroll the preview — don't push the shell. */
    .cp-editor-pane--preview {
        overflow: auto;
    }

    .cp-editor-monaco-host {
        min-height: 0;
    }
}

/* The grid items need to be flex containers so the cp-editor-pane inside fills their height —
   without this, the chat-column's MudPaper collapses to content height and the log doesn't scroll. */
.cp-editor-shell > .mud-grid-item {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.cp-editor-pane {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 16px !important;
}

.cp-editor-pane--chat {
    min-height: 540px;
}

/* Right-column wrapper MudStack: stretch to fill the grid item so the preview pane below can
   flex up to match the chat pane's height. MudStack is `display: flex; flex-direction: column`
   by default; we just need it to fill. */
.cp-editor-shell .mud-grid-item > .mud-stack {
    flex: 1 1 auto;
    min-height: 0;
}

/* Preview pane inside MudStack: takes whatever the toolbar leaves behind, ensuring the chat
   pane's bottom edge and the preview pane's bottom edge line up. */
.cp-editor-pane--preview {
    flex: 1 1 auto;
    min-height: 0;
}

/* Propagate the flex chain through MudTabs internals so the chat panel inside the AI-chat tab
   gets a real height to work with. NOTE: MudBlazor's class is .mud-tab-panel (hyphenated) — NOT
   .mud-tabpanel. The hyphenated form is the one to target. */
.cp-editor-pane .cp-editor-tabs,
.cp-editor-pane .cp-editor-tabs > .mud-tabs-panels,
.cp-editor-pane .cp-editor-tabs .mud-tab-panel {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* Drop MudBlazor's margin-right/margin-inline-end on .mud-tab-icon-text — that 8px push throws
   off the vertical centering between the icon and the label inside our tab strip. Keeping the
   icon directly next to the text reads correctly. Scoped to the editor tabs so we don't change
   MudTabs styling elsewhere in the app. */
.cp-editor-pane .mud-tab .mud-tab-icon-text {
    margin-right: 0;
    margin-inline-end: 0;
}

/* Toolbar above the preview iframe: dirty badge, last-saved timestamp, Save button. Padding
   matched to the panel internals so the right column reads as one consistent block. */
.cp-editor-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    flex-wrap: wrap;
}

.cp-editor-toolbar-spacer {
    flex: 1 1 auto;
}

.cp-editor-save-button {
    flex-shrink: 0;
}

.cp-editor-status-pill {
    font-size: 0.75rem;
}

.cp-editor-status-pill--dirty {
    /* Warning chip already provides the visual; this hook is here for future tweaks. */
}

/* The TabPanelsClass on MudTabs lands on the panel container here. The 24px top padding
   gives the content room to breathe below the tab strip — without this, the chat header
   buttons crash into the tab strip's bottom border. */
.cp-editor-tab-panel {
    padding: 24px 0 0;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* ----- Chat panel (AdChatPanel + AdChatMessage) — ported from BannerChatPanel + BannerChatMessage.
       Role-styled bubbles: user right-aligned with primary tint, assistant left-aligned with a
       robot avatar and surface-tinted background. Empty state with examples, animated thinking
       dots, cost badge in the action row. ----- */

/* CSS Grid for the chat panel — three rows: header (auto), middle (1fr, holds log OR empty
   state), input dock (auto). Grid is more reliable than nested flex for "fixed top + fill
   middle + fixed bottom" because we don't have to chain `min-height: 0` through every
   intermediate flex parent. */
.cp-chat-panel {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    height: 100%;
    width: 100%;
    gap: 12px;
    margin-top: 10px;
}

/* Drag-over affordance — a file is being dragged over the chat panel (registerDropZone in ad-chat.js). */
.cp-chat-panel.cp-chat-dragover {
    outline: 2px dashed var(--mud-palette-primary);
    outline-offset: 4px;
    border-radius: 8px;
    background-color: rgba(var(--mud-palette-primary-rgb), 0.04);
}

.cp-chat-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--mud-palette-divider-light);
    flex-wrap: wrap;
}

.cp-chat-title {
    display: inline-flex;
    align-items: center;
}

.cp-chat-header-spacer {
    flex: 1 1 auto;
}

.cp-chat-log {
    min-height: 0;
    /* No max-height here: the editor shell is viewport-bounded on desktop (see the media query
       under .cp-editor-shell), so the chat panel's 1fr grid row scrolls within that bound and the
       input dock below it stays visible. A fixed max-height here over-cut the dock on short windows. */
    overflow-y: auto;
    padding: 12px;
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
    border: 1px solid var(--mud-palette-divider-light);
}

.cp-chat-empty {
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 32px 16px;
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
    border: 1px dashed var(--mud-palette-divider);
}

/* The input dock anchors at the bottom of the chat panel: pending attachments strip + textarea
   + action row, all stacked. Bordered top so it visually separates from the message log. */
.cp-chat-input-dock {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-divider-light);
}

.cp-chat-empty-icon {
    font-size: 2.5rem !important;
}

.cp-chat-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 10px;
}

.cp-chat-row--user {
    flex-direction: row-reverse;
}

.cp-chat-row--assistant {
    flex-direction: row;
}

.cp-chat-bubble {
    max-width: 78%;
    display: flex;
    flex-direction: column;
}

.cp-chat-row--user .cp-chat-bubble {
    align-items: flex-end;
}

.cp-chat-bubble-card {
    border-radius: 14px;
    line-height: 1.4;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.cp-chat-bubble-card--user {
    background: linear-gradient(135deg, var(--mud-palette-primary) 0%, var(--mud-palette-primary-darken) 100%);
    color: var(--mud-palette-primary-text);
    border-bottom-right-radius: 4px;
}

.cp-chat-bubble-card--assistant {
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider-light);
    border-bottom-left-radius: 4px;
}

.cp-chat-bubble-body {
    font-size: 0.875rem;
}

.cp-chat-bubble-card--user .cp-chat-bubble-body {
    color: var(--mud-palette-primary-text);
}

.cp-chat-timestamp {
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem !important;
    margin-top: 2px;
}

.cp-chat-bubble-attachments {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

.cp-chat-attachment-thumb {
    width: 72px;
    height: 72px;
    border-radius: 6px;
    overflow: hidden;
    background-color: var(--mud-palette-background-gray);
    display: flex;
    align-items: center;
    justify-content: center;
}

    .cp-chat-attachment-thumb img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

.cp-chat-role-icon {
    flex-shrink: 0;
    margin-top: 2px;
}

/* Animated thinking dots while the AI is generating. */
.cp-chat-thinking {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 10px 14px;
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider-light);
    border-radius: 14px;
    border-bottom-left-radius: 4px;
}

    .cp-chat-thinking span {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background-color: var(--mud-palette-text-secondary);
        animation: cp-chat-bounce 1.2s infinite ease-in-out;
    }

        .cp-chat-thinking span:nth-child(2) { animation-delay: 0.15s; }
        .cp-chat-thinking span:nth-child(3) { animation-delay: 0.30s; }

@keyframes cp-chat-bounce {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
    40%           { transform: scale(1.0); opacity: 1.0; }
}

.cp-chat-actions {
    flex-wrap: wrap;
    row-gap: 8px;
}

.cp-chat-cost {
    font-size: 0.75rem !important;
}

/* Drag/paste hint shown next to the Vedhæft button — mirrors BannerGen's chat-input-hint.
   Subdued color, small icon + text.

   It is also the row's spacer, which is why it carries `flex: 1 1 0` instead of a separate
   spacer element. The zero flex-basis matters: with `flex-wrap: wrap` on the parent, line
   breaking is decided from each item's flex BASE size, not its content width — an auto-basis
   hint as wide as its text pushed the Send button onto a second row in the ~1/3-width editor
   column. At basis 0 the hint never forces a break; it grows into whatever space Vedhæft, the
   cost chip and Send leave behind, and truncates with an ellipsis when that runs short. The
   full string stays available via the title attribute. */
.cp-chat-hint {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
    line-height: 1.2;
}

.cp-chat-hint .mud-icon-root {
    flex-shrink: 0;
}

.cp-chat-hint > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Pending-attachments strip — thumbnails the user has uploaded but not yet sent. */
.cp-chat-pending {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 8px;
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
    border: 1px dashed var(--mud-palette-divider);
}

.cp-chat-pending-thumb {
    position: relative;
    width: 72px;
    height: 72px;
    border-radius: 6px;
    overflow: hidden;
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider-light);
    display: flex;
    align-items: center;
    justify-content: center;
}

    .cp-chat-pending-thumb img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

.cp-chat-pending-remove {
    position: absolute;
    top: -6px;
    right: -6px;
    background-color: var(--mud-palette-surface) !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
    padding: 2px !important;
    min-width: 0 !important;
}

/* ----- Preview pane (Phase 4): two-pane comparison + phone-frame mockup ----- */

.cp-preview-compare {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 8px;
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
    border: 1px solid var(--mud-palette-divider-light);
}

.cp-preview-compare-pane {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.cp-preview-compare-label {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.7rem !important;
    text-align: center;
}

.cp-preview-compare-label--proposed {
    color: var(--mud-palette-primary) !important;
}

/* Phone-frame mockup for mobile view-mode. Mirrors BannerPreviewPane's .phone-frame /
   .phone-screen. 391×683 outer shell with a fake notch; 375×667 inner screen wraps the iframe.
   margin: 0 auto centers the phone inside the preview pane horizontally — without this the
   phone hugs the left edge of the wide preview column. */
.cp-preview-phone-frame {
    width: 391px;
    height: 683px;
    background-color: #1f1f1f;
    border-radius: 40px;
    padding: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    position: relative;
    margin: 0 auto;
}

    .cp-preview-phone-frame::before {
        content: "";
        position: absolute;
        top: 14px;
        left: 50%;
        transform: translateX(-50%);
        width: 110px;
        height: 22px;
        background-color: #1f1f1f;
        border-radius: 14px;
        z-index: 1;
    }

.cp-preview-phone-screen {
    width: 375px;
    height: 667px;
    background-color: #ffffff;
    border-radius: 32px;
    overflow: hidden;
    margin: 0 auto;
    position: relative;
}

/* Applied when the iframe is smaller than the phone screen and should sit centered inside it
   (e.g. SpotBanner mobile at natural 300×250 inside a 375×667 phone). Mobile views that fill
   the phone via transform-scale use the base .cp-preview-phone-screen (top-left aligned). */
.cp-preview-phone-screen--fit {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Box sized to the banner's *scaled* dimensions, holding a transform-scaled iframe (which keeps
   its untransformed layout box). Lets .cp-preview-phone-screen--fit center the visible banner
   correctly — e.g. DisplayBanner mobile (980×190 iframe scaled to ~375×73). */
.cp-preview-phone-fit-box {
    overflow: hidden;
    flex: 0 0 auto;
}

.cp-preview-phone-screen--empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 24px;
    background: linear-gradient(180deg, #f5f5f5 0%, #ebebeb 100%);
    color: var(--mud-palette-text-secondary);
}

.cp-editor-code-panel {
    padding-top: 12px;
}

/* Monaco editor host. AutomaticLayout=true measures the parent, so the host needs a real height.
   A fixed height collapsed to ~0 inside the flex column (flex-shrink), leaving only a few px of
   editor — so we flex-fill the bounded editor column instead (.cp-editor-shell is viewport-bounded
   on desktop). min-height is the mobile/fallback floor; the desktop media query resets it to 0 so
   the host fills the available height. margin-top matches .cp-chat-panel for an even gap below the tab strip. */
.cp-editor-monaco-host {
    flex: 1 1 auto;
    min-height: 320px;
    width: 100%;
    border: 1px solid var(--mud-palette-divider);
    border-radius: 6px;
    overflow: hidden;
    margin-top: 10px;
}

/* BlazorMonaco renders a plain container div with no height of its own, so it collapsed to a thin
   line even when the host had height. Make it fill the host (AutomaticLayout then sizes Monaco to it). */
.cp-editor-monaco-host > div {
    height: 100%;
    width: 100%;
}

.cp-editor-preview {
    background-color: #ffffff;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    overflow: hidden;
    margin: 0 auto;
}

.cp-editor-preview-iframe {
    display: block;
    background: #ffffff;
    pointer-events: none;
}

.cp-search-field {
    max-width: 360px;
}

    .cp-search-field .mud-input-slot {
        background-color: var(--mud-palette-surface);
    }

/* ===== Banner review (pin + annotate) ===== */

.cp-banner-canvas {
    position: relative;
    display: inline-block;
    max-width: 100%;
    cursor: crosshair;
    line-height: 0;
}

.cp-banner-image {
    max-width: 100%;
    height: auto;
    display: block;
    border-radius: 8px;
    user-select: none;
}

.cp-banner-pin {
    position: absolute;
    transform: translate(-50%, -50%);
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid #FFFFFF;
    background-color: var(--mud-palette-primary);
    color: #FFFFFF;
    font-weight: 700;
    font-size: 0.85rem;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
    transition: transform 100ms ease-in-out;
    z-index: 5;
}

    .cp-banner-pin:hover {
        transform: translate(-50%, -50%) scale(1.15);
    }

.cp-banner-pin-selected {
    background-color: var(--mud-palette-warning);
    transform: translate(-50%, -50%) scale(1.2);
}

.cp-banner-pin-resolved {
    background-color: var(--mud-palette-success);
    opacity: 0.85;
}

.cp-annotation-panel {
    max-height: 600px;
    overflow-y: auto;
}

.cp-annotation-list {
    /* Tight stacking for comment list */
}

.cp-annotation-item {
    transition: border-color 120ms ease-in-out;
    background-color: var(--mud-palette-surface);
}

    .cp-annotation-item:hover {
        border-color: var(--mud-palette-primary) !important;
    }

.cp-annotation-item-selected {
    border-color: var(--mud-palette-primary) !important;
    background-color: var(--mud-palette-action-default-hover);
}

.cp-annotation-item-resolved {
    opacity: 0.7;
}

.cp-banner-preview {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: contain;
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
}

.cp-kpi-card {
    border-radius: 12px !important;
    background-color: var(--mud-palette-surface);
    transition: transform 120ms ease-in-out, box-shadow 120ms ease-in-out;
}

    .cp-kpi-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.10);
    }

.cp-kpi-label {
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 600;
    font-size: 0.7rem;
    color: var(--mud-palette-text-secondary);
}

.cp-kpi-value {
    font-weight: 600;
    line-height: 1.1;
    color: var(--mud-palette-text-primary);
}

/* ===== Account avatar + popout ===== */

/* One identity color per person, shared by the activator avatar and the popover-header avatar
   so the same user reads consistently. Mirrors the workspace presence-chip convention:
   blue = L-Mediehus staff (CMSUser), orange = customer. */
.cp-account-avatar--cms {
    background-color: #3b82f6 !important;
    color: #fff !important;
}

.cp-account-avatar--customer {
    background-color: #f97316 !important;
    color: #fff !important;
}

/* The account block is the positioning context for the inline popout. */
.cp-account {
    position: relative;
}

/* Inline popout: a real child of the footer spanning its width (left:0; right:0), so it always
   sits within the sidebar — horizontally centered — and opens upward above the account button.
   Unlike MudMenu it isn't portaled to <body>, so it can't escape the sidebar. */
.cp-account-popout {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + 6px);
    z-index: 30;
    background-color: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
    overflow: hidden;
    padding: 4px 0;
}

/* Header: identity row (avatar + name/email) with the role chip on its own line below. */
.cp-account-popout-header {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px;
}

.cp-account-popout-identity {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

/* Menu rows — left-aligned icon + label, read like nav links. */
.cp-account-item {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    width: 100%;
    padding: 10px 14px;
    cursor: pointer;
    font-size: 0.875rem;
    line-height: 1.2;
    color: var(--mud-palette-text-primary);
    text-align: left;
    transition: background-color 120ms ease-in-out;
}

    .cp-account-item:hover {
        background-color: var(--mud-palette-action-default-hover);
    }

/* Active row — mirrors the sidebar nav-link active style (primary tint + bold + primary icon). */
.cp-account-item--active {
    background-color: var(--mud-palette-primary-hover);
    color: var(--mud-palette-primary);
    font-weight: 600;
}

    .cp-account-item--active .cp-account-item-icon {
        color: var(--mud-palette-primary);
    }

.cp-account-item-icon {
    color: var(--mud-palette-text-secondary);
}

.cp-account-item--danger {
    color: var(--mud-palette-error);
}

    .cp-account-item--danger .cp-account-item-icon {
        color: var(--mud-palette-error);
    }

/* Compact activator avatar (~30px) with proportional initials — Size.Small (24px) + body2
   text made the two letters look oversized next to the well-proportioned 40px popout avatar. */
.cp-account-activator .cp-account-avatar {
    width: 30px;
    height: 30px;
}

/* ===== Auth shell (login, forgot/reset password) ===== */

.cp-auth-shell {
    min-height: 100vh;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(circle at 20% 20%, rgba(30, 64, 175, 0.10), transparent 45%),
        radial-gradient(circle at 80% 80%, rgba(8, 145, 178, 0.08), transparent 50%),
        var(--mud-palette-background);
    padding: 2rem 1rem;
}

.cp-auth-card-wrapper {
    width: 100%;
    max-width: 28rem;
}

.cp-auth-card {
    border-radius: 16px !important;
    background-color: var(--mud-palette-surface);
}

/* ===== Utility text overrides for MudBlazor secondary text ===== */

.mud-text-secondary {
    color: var(--mud-palette-text-secondary) !important;
}
