#od-upload-widget {
    position: fixed;
    top: 80px;
    right: 20px;
    width: 360px;
    max-width: calc(100vw - 40px);
    background: #fff;
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.18);
    z-index: 9999;
    font-size: 13px;
    display: none;
    overflow: hidden;
}
#od-upload-widget.visible { display: block; }
#od-upload-widget .od-uw-header {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    background: #f5f5f5;
    border-bottom: 1px solid #e0e0e0;
    cursor: pointer;
    user-select: none;
}
#od-upload-widget .od-uw-title {
    flex: 1;
    font-weight: 600;
    color: #333;
}
#od-upload-widget .od-uw-actions a {
    margin-left: 10px;
    color: #666;
    text-decoration: none;
    cursor: pointer;
}
#od-upload-widget .od-uw-actions a:hover { color: #000; }
#od-upload-widget .od-uw-actions .js-od-uw-cancel-all:hover { color: #d33; }
#od-upload-widget .od-uw-list {
    max-height: 280px;
    overflow-y: auto;
    /* Flex column so rows can be visually reordered by `order` (below) without
       touching the DOM — O(1) per status change even with thousands of rows. */
    display: flex;
    flex-direction: column;
}
#od-upload-widget.collapsed .od-uw-list { display: none; }
/* Float actively-transferring files to the top, sink finished ones to the
   bottom; queued/preparing rows sit in between. `order` only reorders the
   visual flow, so a file changing status is a cheap style recalc, not a
   reflow of the whole list. */
#od-upload-widget .od-uw-item { order: 1; }            /* preparing / queued */
#od-upload-widget .od-uw-item.uploading { order: 0; }  /* actively transferring */
#od-upload-widget .od-uw-item.done,
#od-upload-widget .od-uw-item.error { order: 2; }      /* finished */
#od-upload-widget .od-uw-item {
    padding: 8px 12px;
    border-bottom: 1px solid #f0f0f0;
    /* Offscreen rows in a long queue (hundreds/thousands of files) skip layout
       and paint — keeps scrolling smooth without virtualization. The intrinsic
       size matches the rendered row height so the scrollbar sizes correctly. */
    content-visibility: auto;
    contain-intrinsic-size: 0 60px;
}
#od-upload-widget .od-uw-item:last-child { border-bottom: none; }
#od-upload-widget .od-uw-item-row {
    display: flex;
    align-items: center;
    margin-bottom: 4px;
}
#od-upload-widget .od-uw-icon {
    margin-right: 8px;
    color: #888;
    flex-shrink: 0;
    width: 14px;
    text-align: center;
}
#od-upload-widget .od-uw-item.done .od-uw-icon { color: #4caf50; }
#od-upload-widget .od-uw-item.error .od-uw-icon { color: #d33; }
#od-upload-widget .od-uw-name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #222;
}
#od-upload-widget .od-uw-size {
    font-size: 11px;
    color: #777;
    flex-shrink: 0;
}
#od-upload-widget .od-uw-cancel {
    margin-left: 8px;
    color: #aaa;
    text-decoration: none;
    flex-shrink: 0;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
}
#od-upload-widget .od-uw-cancel:hover { color: #d33; }
#od-upload-widget .od-uw-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 4px;
    font-size: 11px;
    color: #777;
}
#od-upload-widget .od-uw-meta .od-uw-size { flex: 1; }
#od-upload-widget .od-uw-meta .od-uw-speed { flex-shrink: 0; }
#od-upload-widget .od-uw-meta .od-uw-eta {
    flex-shrink: 0;
    color: #888;
}
#od-upload-widget .od-uw-meta .od-uw-speed:empty,
#od-upload-widget .od-uw-meta .od-uw-eta:empty { display: none; }
#od-upload-widget .od-uw-bar {
    height: 4px;
    background: #eee;
    border-radius: 2px;
    overflow: hidden;
}
#od-upload-widget .od-uw-bar-fill {
    height: 100%;
    width: 0;
    background: #2a8ee8;
    transition: width 0.2s linear;
}
#od-upload-widget .od-uw-item.done .od-uw-bar-fill { background: #4caf50; }
#od-upload-widget .od-uw-item.error .od-uw-bar-fill { background: #d33; }
/* Preparing: nothing is transferring yet (folders being created / collisions
   checked). Show an indeterminate striped bar so the row reads as "working",
   not as a stalled 0% upload. The fill is held at 100% width by JS. */
#od-upload-widget .od-uw-item.preparing .od-uw-bar-fill {
    background-image: linear-gradient(
        -45deg,
        rgba(255,255,255,0.35) 25%, transparent 25%,
        transparent 50%, rgba(255,255,255,0.35) 50%,
        rgba(255,255,255,0.35) 75%, transparent 75%, transparent
    );
    background-size: 16px 16px;
    background-color: #9bbfe0;
    animation: od-uw-stripes 0.8s linear infinite;
}
#od-upload-widget .od-uw-item.preparing .od-uw-icon { color: #2a8ee8; }
#od-upload-widget .od-uw-item.preparing .od-uw-size { font-style: italic; }
@keyframes od-uw-stripes {
    from { background-position: 0 0; }
    to   { background-position: 16px 0; }
}
#od-upload-widget .od-uw-overflow {
    padding: 6px 12px;
    text-align: center;
    color: #888;
    font-size: 11px;
    background: #fafafa;
    border-top: 1px solid #f0f0f0;
}
