.loading-card,
.upload-card,
.media-card {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    overflow: hidden;
    background: var(--color-rov-light-gray);
}

/* Ensure all media types respect card boundaries */
.media-card > * {
    max-width: 100%;
    max-height: 100%;
}

.upload-card:focus,
.media-card:focus {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}

.upload-card:focus:not(:focus-visible),
.media-card:focus:not(:focus-visible) {
    outline: none;
}

.upload-card:focus-visible,
.media-card:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}

.upload-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: var(--color-rov-light-gray);
    padding: 1rem;
}

/* Sorting styles */
.media-card {
    cursor: move;
    cursor: grab;
    touch-action: pan-y;
    user-select: none;
    -webkit-user-select: none;
}

.media-card:active {
    cursor: grabbing;
}

.sortable-ghost {
    opacity: 0.3;
}

.sortable-drag {
    opacity: 0.9;
}

/* Prevent upload card from being draggable */
.upload-card {
    cursor: default !important;
}

/* Upload card */
.upload-card {
    background: var(--color-rov-light-gray);
    cursor: pointer;
}

/* ============================================
   Uppy upload card (W7 — replaced FilePond)
   ============================================ */

/* Keep the drop zone the SAME square cell as a media card — aspect-ratio:1 +
   overflow:hidden come from the shared base rule at the top — so it flows as
   the first item in the grid (drop zone, photo, photo → photo, photo, photo)
   instead of a tall cell that leaves a gap under the first row. The Uppy
   Dashboard fills the square rather than dictating the cell height. */
.upload-card:has(.rov-uppy-target) {
    padding: 0;
    display: block;
}

.rov-uppy-target {
    width: 100%;
    height: 100%;
}

/* Uppy's Dashboard defaults to a FIXED 750px width and 300px height — inside a
   grid cell that both blows the track open AND makes the drop zone taller than
   the photo cells. Force it to fill the square card instead. */
.rov-uppy-target .uppy-Root,
.rov-uppy-target .uppy-Dashboard {
    width: 100%;
    height: 100%;
    min-width: 0;
}

.rov-uppy-target .uppy-Dashboard-inner {
    width: 100%;
    min-width: 0;
    /* Beat Uppy's inline height:300 so the Dashboard matches the square cell. */
    height: 100% !important;
    min-height: 0 !important;
}

/* Blend the Dashboard into the card chrome. */
.rov-uppy-target .uppy-Dashboard-inner {
    border: none;
    border-radius: 4px;
    background-color: transparent;
}

.rov-uppy-target .uppy-Dashboard-dropFilesHereHint {
    border-color: var(--color-border);
}

.rov-uppy-target .uppy-Dashboard-note {
    color: #6c757d;
}

/* Disabled state at the media limit — Uppy applies aria-disabled; make it read. */
.rov-uppy-target .uppy-Dashboard-inner[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

/* Media Grid Styles */
.media-grid-container {
    display: grid;
    /* minmax(0,1fr): keep children (the Uppy Dashboard is 750px-wide by
       default) from blowing out the tracks — the card shrinks, not the grid */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
    width: 100%;
}

/* Responsive adjustments - small screens use auto-fill for both contexts */
@media (max-width: 768px) {
    .media-grid-container {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }
}

/* Offcanvas context - max 3 columns since space is limited */
[data-in-offcanvas="true"] .media-grid-container {
    grid-template-columns: repeat(3, 1fr);
}

/* Small screens in offcanvas still use auto-fill */
@media (max-width: 768px) {
    [data-in-offcanvas="true"] .media-grid-container {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }
}

.media-content {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 0;
    left: 0;
}

.media-card img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    display: block;
}

.media-card video,
.media-card iframe {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
}

/* Video play overlay (YouTube, Bunny) */
.video-play-overlay,
.bunny-play-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 3rem;
    color: rgba(255, 255, 255, 0.85);
    pointer-events: none;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.media-content {
    position: relative;
}

.media-card audio {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 90%;
}

.media-caption {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.5rem;
    background: rgba(255, 255, 255, 0.9);
    opacity: 0;
    transition: opacity 0.2s;
    /* Hide empty captions completely */
    display: none;
}

/* Only show non-empty captions */
.media-caption:not(:empty) {
    display: block;
}

.media-card:hover .media-caption:not(:empty) {
    opacity: 1;
}

/* Deleting animation - optimistic delete with red glow */
.media-card.deleting {
    animation: deleteGlow 0.5s ease-out forwards;
    pointer-events: none;
}

@keyframes deleteGlow {
    0% {
        opacity: 1;
        transform: scale(1);
        box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
    }
    30% {
        box-shadow: 0 0 20px 5px rgba(220, 53, 69, 0.6);
    }
    100% {
        opacity: 0;
        transform: scale(0.9);
        box-shadow: 0 0 30px 10px rgba(220, 53, 69, 0);
    }
}

/* Media card icon container (bottom-right icons) */
.media-card-icons {
    position: absolute;
    bottom: 0.5rem;
    right: 0.5rem;
    z-index: 1;
    display: flex;
    gap: 0.4rem;
}

/* Base icon styling */
.rovEditMediaIcon,
.rovCaptionIcon,
.rovDeleteMediaIcon,
.deleteMediaIcon {
    cursor: pointer;
    color: white;
    text-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
    font-size: 1rem;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid rgba(255, 255, 255, 0.8);
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.3);
    transition: background 0.2s, border-color 0.2s, opacity 0.2s;
}

/* Trash icon positioned at top-right */
.media-card > .deleteMediaIcon {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 1;
}

/* Featured-image preview shown in the widget collapse */
#currentFeaturedImage img {
    max-width: 400px;
    max-height: 200px;
    object-fit: cover;
    height: auto;
}

/* Featured-image source badge — bottom-left, low-attention */
.media-card > .featuredSourceBadge {
    position: absolute;
    bottom: 0.5rem;
    left: 0.5rem;
    z-index: 1;
    color: rgba(255, 255, 255, 0.9);
    font-size: 0.85rem;
    width: 1.75rem;
    height: 1.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.35);
    opacity: 0.6;
    cursor: default;
    transition: opacity 0.15s ease;
}

.media-card > .featuredSourceBadge:hover {
    opacity: 1;
}

/* Hover label */
.media-card > .featuredSourceBadge::after {
    content: 'Featured image';
    position: absolute;
    bottom: calc(100% + 4px);
    left: 0;
    background: rgba(17, 24, 39, 0.95);
    color: white;
    font-size: 0.7rem;
    padding: 0.2rem 0.45rem;
    border-radius: 0.25rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease;
}

.media-card > .featuredSourceBadge:hover::after {
    opacity: 1;
}

/* Desktop: subtle opacity states */
@media (hover: hover) {
    /* Default: very subtle */
    .media-card-icons,
    .media-card > .deleteMediaIcon {
        opacity: 0.5;
    }

    /* Card hover: slightly more visible */
    .media-card:hover .media-card-icons,
    .media-card:hover > .deleteMediaIcon {
        opacity: 0.7;
    }

    /* Icon hover: full opacity */
    .media-card .rovEditMediaIcon:hover,
    .media-card .rovCaptionIcon:hover,
    .media-card .deleteMediaIcon:hover {
        opacity: 1;
        background: rgba(0, 0, 0, 0.5);
        border-color: white;
    }

    .media-card:hover .media-caption:not(:empty) {
        opacity: 1;
        font-size: 0.8rem;
        line-height: 1.2;
    }
}

/* Mobile: always full opacity */
@media (hover: none) {
    .media-card-icons,
    .media-card > .deleteMediaIcon {
        opacity: 1;
    }

    .media-caption:not(:empty) {
        opacity: 1;
    }
}

/* Processing Area Styles */
#rovMediaGridContainer.processing-new-files #rovMediaGrid {
    opacity: 0.5;
    pointer-events: none;
    max-height: 240px;
    overflow: hidden;
    transition: all 0.3s ease;
    margin-bottom: 2rem;
    position: relative;
}

#rovMediaGridContainer.processing-new-files #rovMediaGrid::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 50px;
    background: linear-gradient(transparent, white);
}

#rovMediaGridContainer.processing-new-files #mediaProcessingArea {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin: 1rem 0;
}

#mediaProcessingAreaContainer {
    display: none;
}

#rovMediaGridContainer.processing-new-files #mediaProcessingAreaContainer {
    display: block;
    background: var(--color-rov-light-gray);
    border-radius: 8px;
    border: 2px dashed var(--color-border);
    padding: 1em;
}

.preview-image {
    background-size: cover;
    background-position: center;
    width: 100%;
    height: 160px;
    position: relative;
}

.preview-video {
    position: relative;
    width: 100%;
    height: 160px;
}

.preview-video video {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
}

.processing-item-delete {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    z-index: 10;
    background: transparent;
    border: none;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    cursor: pointer;
}

.processing-item-delete i {
    font-size: 0.875rem;
    -webkit-text-stroke: 1px black;
    text-stroke: 1px black;
    filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.8));
}

@media (min-width: 768px) {
    #rovMediaGridContainer.processing-new-files #mediaProcessingArea {
        grid-template-columns: repeat(3, 1fr);
        padding: 2rem 0;
    }
    .preview-image,
    .preview-video {
        height: 200px;
    }
}

/* Placeholder card (uploading state in media grid) */
.media-card.placeholder {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    pointer-events: none;
}

.media-card.placeholder .placeholder-overlay {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: white;
}

.media-card.placeholder.error {
    pointer-events: auto;
    cursor: pointer;
}

.media-card.placeholder.error .placeholder-overlay {
    background: rgba(220, 53, 69, 0.7);
}

.media-card.placeholder .error-message {
    position: absolute;
    inset: 0;
    color: white;
    font-weight: 500;
    font-size: 0.8rem;
    background: rgba(220, 53, 69, 0.7);
}

#mediaEditPreview img {
    max-height: 60vh;
}

/* ============================================
   Selection Mode Styles
   ============================================ */

/* Selection bar */
.selection-bar {
    margin-bottom: 1rem;
}

/* Checkbox overlay on cards */
.selection-checkbox {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    z-index: 10;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
    transition: transform 0.15s, background-color 0.15s;
}

.selection-checkbox:hover {
    transform: scale(1.1);
    background: white;
}

.selection-checkbox i {
    font-size: 18px;
}

.selection-checkbox .unchecked {
    color: var(--color-text-secondary);
}

.selection-checkbox .checked {
    color: var(--color-focus-ring);
}

/* Selectable card styling */
.media-card.selectable {
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
}

.media-card.selectable:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* Selected card styling */
.media-card.selected {
    outline: 3px solid var(--color-focus-ring);
    outline-offset: -3px;
}

.media-card.selected::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(13, 110, 253, 0.1);
    pointer-events: none;
}

/* Hide card actions in selection mode */
.selection-mode-active .media-card.selectable .media-card-icons,
.selection-mode-active .media-card.selectable .rovEditMediaIcon,
.selection-mode-active .media-card.selectable .rovDeleteMediaIcon,
.selection-mode-active .media-card.selectable .deleteMediaIcon {
    display: none;
}

/* Disable drag cursor in selection mode */
.selection-mode-active .media-card {
    cursor: default;
}

.selection-mode-active .media-card.selectable {
    cursor: pointer;
}

/* Non-selectable cards in selection mode (video, youtube, audio) */
.selection-mode-active .media-card:not(.selectable) {
    opacity: 0.5;
    filter: grayscale(50%);
}

/* Responsive adjustments for selection bar */
@media (max-width: 576px) {
    .selection-bar .flex {
        flex-direction: column;
        gap: 0.5rem;
    }

    .selection-bar .selection-actions {
        width: 100%;
        justify-content: space-between;
    }
}

/* ============================================
   Media Studio Processing Overlay
   ============================================ */

/* Processing state for media cards */
.media-card.media-studio-processing {
    pointer-events: none;
}

.media-card.media-studio-processing img {
    opacity: 0.4;
    filter: grayscale(30%);
    transition: opacity 0.3s, filter 0.3s;
}

.media-studio-processing-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.3);
    z-index: 20;
}

/* ============================================
   Accept-All in-progress feedback (W7)
   ============================================ */

/* Lock every per-item action in the staging area while the batch uploads so
   nothing reads as clickable mid-flight. The Accept All button itself stays
   full-opacity — it shows the live "Uploading X/Y" counter. */
.is-accepting button:not(.js-accept-all-btn) {
    pointer-events: none;
    opacity: 0.45;
}

/* Every queued item gets a veil + spinner so it's clear the whole batch is
   being transferred, not just the one currently uploading. */
.processing-item.is-uploading::before {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, 0.55);
    z-index: 2;
    border-radius: 4px;
}

.processing-item.is-uploading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 28px;
    height: 28px;
    margin: -14px 0 0 -14px;
    border: 3px solid rgba(0, 0, 0, 0.15);
    border-top-color: var(--color-rov-green, #1f9d55);
    border-radius: 50%;
    z-index: 3;
    animation: rovProcessingSpin 0.8s linear infinite;
}

@keyframes rovProcessingSpin {
    to { transform: rotate(360deg); }
}

.processing-item.is-uploading {
    position: relative;
}

/*
 * Edit lineage — the sparkle badge and the version arrows.
 *
 * Plain CSS rather than utilities because these are server-rendered into a
 * sprintf'd card string in MediaPresenter, which sits alongside the rest of
 * the card's chrome (.deleteMediaIcon, .featuredSourceBadge) already styled
 * here. Splitting one card's appearance across two systems would cost more
 * than it saves.
 */


/*
 * Version strip. Over the thumbnail rather than below it: the grid's rows are
 * a fixed height, so a control under the image would either crop the picture
 * or reflow every card on the page the moment one image gained a version.
 *
 * Top-centre, not bottom-centre: bottom-centre put it straight through the
 * edit and caption icons on a 180px card, and the right arrow rendered
 * merged into the paint-brush button.
 */
.media-card .media-version-nav {
    position: absolute;
    top: 0.5rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
}

/*
 * The pill itself — identical in the gallery card, the Media Studio preview
 * and the caption modal, because it is literally the same markup rendered by
 * MediaPresenter::renderVersionNav() and MediaVersionChooser.render().
 */
.media-version-nav {
    display: flex;
    align-items: center;
    gap: 0.125rem;
    padding: 0.125rem 0.25rem;
    border-radius: 999px;
    background: rgba(17, 24, 39, 0.7);
    backdrop-filter: blur(2px);
    transition: opacity 0.15s ease;
}

/* Only ON A CARD does it sit over the reader's photo, so only there does it
   get out of the way until the card is hovered. In the studio and caption
   modal it is a control in its own right and stays fully present. */
.media-card .media-version-nav {
    opacity: 0.75;
}

.media-card:hover .media-version-nav,
.media-card .media-version-nav:hover {
    opacity: 1;
}

.media-version-nav button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #fff;
    font-size: 0.65rem;
    cursor: pointer;
}

.media-version-nav button:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.2);
}

/* Kept visible, not hidden: the gap tells you which end of the strip you
   are at. A disappearing arrow reads as a rendering fault. */
.media-version-nav button:disabled {
    opacity: 0.3;
    cursor: default;
}

.media-version-count {
    color: #fff;
    font-size: 0.625rem;
    font-variant-numeric: tabular-nums;
    padding: 0 0.125rem;
    user-select: none;
}

/* Provenance rides inside the pill rather than as a second badge: it
   describes the version the arrows are pointing at, and changes as you step. */
.media-version-ai {
    color: #fff;
    font-size: 0.7rem;
    padding: 0 0.25rem 0 0.125rem;
    opacity: 0.95;
    cursor: default;
}
