/* Stored — bring-your-own-bucket file explorer. The canvas is one
   wide column: connection picker + breadcrumb on top, file list
   below, footer pinned to the viewport bottom. */

body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.appLayout {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-top: var(--header-height);
    background: var(--bg);
}

.storedPage {
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 24px 24px 120px;
}

/* ── Header strip: connection picker + new-folder + upload ───────── */
.storedToolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.storedConnectionPicker {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);
}
.storedConnectionPicker:hover { border-color: var(--border-strong); background: var(--bg-hover); }
.storedConnectionPicker .fa-cloud { color: var(--text-tertiary); font-size: 14px; }
.storedConnectionPickerText {
    font-size: 13.5px;
    color: var(--text);
    font-weight: 500;
}
.storedConnectionPickerHint {
    font-size: 11.5px;
    color: var(--text-tertiary);
    margin-left: 4px;
}
.storedConnectionPicker .fa-chevron-down { font-size: 10px; color: var(--text-tertiary); }

.storedToolbarSpacer { flex: 1; }

/* Search row — full-width strip pinned right above the file table.
   Used to live inside the toolbar between the picker and the action
   buttons; got hoisted out so it has a roomy hit target on any
   viewport. Debounced on input → recursive bucket search; ESC
   clears. */
.storedSearchRow {
    margin-bottom: 10px;
}
.storedSearchWrap {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
}
.storedSearchIcon {
    position: absolute;
    left: 13px;
    color: var(--text-tertiary);
    font-size: 13px;
    pointer-events: none;
}
.storedSearchInput {
    width: 100%;
    padding: 10px 14px 10px 36px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.storedSearchInput::placeholder { color: var(--text-tertiary); }
.storedSearchInput:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Free-tier usage chip — only rendered next to the picker on the
   Toothpaste-managed connection. The bar fill goes mint while the
   user is comfortable, amber at 80%+, red when they're at or over
   the 1 GB ceiling (paired with a disabled Upload button). */
.storedUsageChip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 12px;
    color: var(--text-secondary);
    background: var(--bg);
    white-space: nowrap;
}
.storedUsageText { font-variant-numeric: tabular-nums; }
.storedUsageBar {
    width: 64px;
    height: 4px;
    background: var(--bg-sidebar);
    border-radius: 2px;
    overflow: hidden;
    flex-shrink: 0;
}
.storedUsageBarFill {
    display: block;
    height: 100%;
    width: 0;
    background: var(--mint);
    transition: width 200ms ease, background 200ms ease;
}
.storedUsageBarFill.warning { background: #e0a852; }
.storedUsageBarFill.over    { background: #c33; }

.storedToolbarBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.storedToolbarBtn:hover { color: var(--text); background: var(--bg-hover); border-color: var(--text-tertiary); }
.storedToolbarBtn:disabled { opacity: 0.5; cursor: not-allowed; }
.storedToolbarBtn--primary {
    background: var(--accent);
    color: var(--bg-sidebar);
    border-color: transparent;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10), inset 0 1px 0 rgba(255, 255, 255, 0.08);
}
/* Hold the accent fill on hover — without an explicit override here
   the parent .storedToolbarBtn:hover rule swaps in --bg-hover for the
   background, giving us light text on a now-light surface (which
   reads as "the button vanishes"). */
.storedToolbarBtn--primary:hover {
    background: var(--accent);
    color: var(--bg-sidebar);
    border-color: transparent;
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.12);
    transform: translateY(-0.5px);
}

/* Connection-picker popover (lists every connection + "New connection"). */
.storedConnectionMenu {
    position: fixed;
    z-index: 200;
    min-width: 280px;
    padding: 6px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    display: none;
}
.storedConnectionMenu[data-open="true"] { display: block; }
.storedConnectionMenuHead {
    padding: 6px 10px 8px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-tertiary);
}
.storedConnectionMenuItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 0;
    color: var(--text);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition);
}
.storedConnectionMenuItem:hover { background: var(--bg-hover); }
.storedConnectionMenuItem.active { background: var(--accent-soft); }
.storedConnectionMenuItemBucket {
    font-size: 11.5px;
    color: var(--text-tertiary);
    margin-left: auto;
}
.storedConnectionMenuDivider { height: 1px; background: var(--border); margin: 4px 4px; }

/* Connection rows in the chooser get an inline "Default" pill on the
   suite-default bucket and a kebab on the right that opens a small
   per-connection action menu (set default, edit, delete). The kebab
   button is a sibling of the connection button — clicking it must
   not also fire the row's open-this-connection handler. */
.storedConnectionMenuRow {
    display: flex;
    align-items: center;
    gap: 2px;
}
.storedConnectionMenuRow > .storedConnectionMenuItem {
    flex: 1;
    min-width: 0;
}
.storedConnectionDefaultBadge {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mint);
    background: var(--mint-soft);
    border-radius: 999px;
    padding: 2px 8px;
    margin-left: 6px;
    flex-shrink: 0;
}
.storedConnectionMenuKebab {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.storedConnectionMenuKebab:hover {
    background: var(--bg-hover);
    color: var(--text);
}

/* Per-connection action submenu — anchored next to the kebab. Uses
   the same shape as .storedRowMenuPopover so the visual language
   stays consistent. */
.storedConnectionActionMenu {
    position: fixed;
    z-index: 220;
    min-width: 200px;
    padding: 4px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    display: none;
}
.storedConnectionActionMenu[data-open="true"] { display: block; }
.storedConnectionActionItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 0;
    color: var(--text);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}
.storedConnectionActionItem:hover { background: var(--bg-hover); }
.storedConnectionActionItem i { width: 14px; color: var(--text-tertiary); font-size: 12px; }
.storedConnectionActionItem.danger { color: #c33; }
.storedConnectionActionItem.danger i { color: #c33; }
.storedConnectionActionItem[disabled] { opacity: 0.45; cursor: default; }

/* ── Breadcrumb ──────────────────────────────────────────────────── */
.storedBreadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px 0;
    margin-bottom: 8px;
    font-size: 13px;
    color: var(--text-secondary);
}
.storedBreadcrumbItem {
    background: transparent;
    border: 0;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.storedBreadcrumbItem:hover { background: var(--bg-hover); color: var(--text); }
.storedBreadcrumbItem--current { color: var(--text); font-weight: 500; cursor: default; }
.storedBreadcrumbItem--current:hover { background: transparent; }
.storedBreadcrumbSep { color: var(--text-tertiary); padding: 0 2px; }
/* Kebab on the breadcrumb — actions on the folder you're inside.
   Sits flush after the current-folder pill; same hit target shape
   as the row kebabs so the affordance reads as identical. */
.storedBreadcrumbMenu {
    width: 28px;
    height: 28px;
    margin-left: 2px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background var(--transition), color var(--transition);
}
.storedBreadcrumbMenu:hover { background: var(--bg-hover); color: var(--text); }
.storedBreadcrumbMenu[aria-expanded="true"] { background: var(--bg-hover); color: var(--text); }

/* ── File table ──────────────────────────────────────────────────── */
.storedList {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg);
}
.storedListHeader,
.storedRow {
    display: grid;
    grid-template-columns: 1fr 110px 180px 40px;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
}
.storedListHeader {
    background: var(--bg-sidebar);
    border-bottom: 1px solid var(--border);
    color: var(--text-tertiary);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 600;
}
/* Clickable sort headers (Name, Modified). Inherits the header's
   uppercase / letter-spacing so the button still reads as a label,
   not a chip. The sort icon dims when the column is idle and goes
   accent-mint when it's the active sort. */
.storedSortBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0;
    margin: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
    user-select: none;
    transition: color var(--transition);
    text-align: left;
}
.storedSortBtn:hover { color: var(--text-secondary); }
.storedSortBtn.is-active { color: var(--text); }
.storedSortIcon { font-size: 10px; }
.storedSortIcon--idle   { opacity: 0.4; }
.storedSortIcon--active { color: var(--mint); opacity: 1; }
.storedRow {
    border-bottom: 1px solid var(--border);
    transition: background var(--transition);
    cursor: pointer;
}
.storedRow:last-child { border-bottom: 0; }
.storedRow:hover { background: var(--bg-hover); }
.storedRow.dragover { background: var(--accent-soft); }

.storedRowName {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}
.storedRowIcon {
    flex-shrink: 0;
    width: 22px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 15px;
}
.storedRow--folder .storedRowIcon { color: var(--mint); }
.storedRowText {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
    color: var(--text);
}
.storedRowSize, .storedRowDate {
    font-size: 12.5px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.storedRowMenu {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    border-radius: 4px;
    opacity: 0;
    transition: opacity var(--transition), background var(--transition), color var(--transition);
    cursor: pointer;
    font-size: 14px;
    justify-self: end;
}
.storedRow:hover .storedRowMenu,
.storedRowMenu[aria-expanded="true"] { opacity: 1; }
.storedRowMenu:hover { color: var(--text); background: var(--bg-hover); }
@media (hover: none) {
    .storedRowMenu { opacity: 1; }
}

.storedListEmpty {
    padding: 56px 24px;
    text-align: center;
    color: var(--text-secondary);
}
.storedListEmptyTitle {
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 6px;
}
.storedListEmptySub { font-size: 13px; }

.storedSearchMore {
    padding: 16px 24px;
    text-align: center;
    border-top: 1px solid var(--border);
}

.storedDropOverlay {
    position: fixed;
    inset: 0;
    background: rgba(46, 196, 182, 0.12);
    border: 3px dashed var(--mint);
    pointer-events: none;
    z-index: 90;
    display: none;
    align-items: center;
    justify-content: center;
    color: var(--mint);
    font-weight: 600;
    font-size: 18px;
}
.storedDropOverlay[data-open="true"] { display: flex; }

/* ── Upload progress strip (above the file list) ─────────────────── */
.storedUploads {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    margin-bottom: 12px;
    padding: 6px;
    display: none;
}
.storedUploads[data-open="true"] { display: block; }
/* Strip header — counter (X of Y) on the left, live speed + ETA
   on the right. Sits above the per-file rows once the queue has
   been seeded; goes empty / quiet once everything settles. */
.storedUploadHeader {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 6px 8px 8px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 4px;
    font-size: 12px;
}
.storedUploadHeaderCounter {
    font-weight: 600;
    color: var(--text);
}
.storedUploadHeaderStats {
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.storedUploadRow {
    display: grid;
    grid-template-columns: 1fr 100px 80px 24px;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
    font-size: 12.5px;
}
.storedUploadRow + .storedUploadRow { border-top: 1px solid var(--border); }
.storedUploadName {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
}
.storedUploadBar {
    height: 6px;
    background: var(--bg-sidebar);
    border-radius: 3px;
    overflow: hidden;
}
.storedUploadBarFill {
    height: 100%;
    background: var(--mint);
    width: 0;
    transition: width 200ms ease;
}
.storedUploadStatus {
    font-size: 11.5px;
    color: var(--text-tertiary);
    text-align: right;
}
.storedUploadStatus.error { color: #c33; }
.storedUploadStatus.done { color: #1f6b3d; }
.storedUploadStatus.paused { color: #b46308; }
/* Inline "Resume" chip — replaces the status label on a paused row
   when the in-memory File is still alive (i.e. retries exhausted but
   no page reload). */
.storedUploadResumeBtn {
    appearance: none;
    border: 1px solid var(--border-strong);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: 11.5px;
    padding: 2px 8px;
    border-radius: 999px;
    cursor: pointer;
    line-height: 1.2;
}
.storedUploadResumeBtn:hover { background: var(--bg-hover); }
/* Tiny ✕ in the row's trailing 24px column — used to dismiss a
   paused upload (calls ?action=abort on the server). */
.storedUploadDismiss {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    font-size: 13px;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
.storedUploadDismiss:hover { background: var(--bg-hover); color: var(--text); }
/* >100 MB info hint: rendered between header and rows when the
   current upload contains a large file/folder. Reuses the muted
   typography of .formFieldHint but with strip-row gutters. */
.storedUploadHint {
    display: flex;
    gap: 6px;
    align-items: flex-start;
    padding: 6px 10px 8px;
    margin: 0 0 4px;
    border-bottom: 1px solid var(--border);
    color: var(--text-tertiary);
    font-size: 11.5px;
    line-height: 1.45;
}
.storedUploadHint i { padding-top: 2px; }

/* ── Onboarding card (when there are no connections yet) ─────────── */
.storedOnboard {
    margin: 32px 0;
    padding: 28px 24px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius);
    background: var(--bg);
    text-align: center;
}
.storedOnboardTitle {
    font-size: 18px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
}
.storedOnboardSub {
    font-size: 13.5px;
    color: var(--text-secondary);
    margin-bottom: 18px;
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
    line-height: 1.5;
}

/* ── Connection-form modal (Add / Edit) ──────────────────────────── */
.confirmModalContent--wide {
    width: 480px;
}
.formField { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
/* [hidden] ties on specificity with the .formField display rule, so
   without this the connection-form fields ignore .hidden = true and
   stay visible when switching providers (AWS region picker leaks into
   the Cloudflare R2 form, etc.). */
.formField[hidden], .formFieldCheckboxRow[hidden] { display: none; }
.formFieldLabel {
    font-size: 11.5px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-secondary);
}
.formFieldHint {
    font-size: 11.5px;
    color: var(--text-tertiary);
    margin-top: 2px;
}
.formFieldRow { display: flex; gap: 10px; }
.formFieldRow > .formField { flex: 1; }
.formFieldCheckboxRow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    font-size: 13px;
    color: var(--text-secondary);
}
.formFieldCheckboxRow input { accent-color: var(--accent); width: 14px; height: 14px; }

/* ── Provider picker (Add a bucket → which kind?) ─────────────────── */
.connProviderGrid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    margin: 14px 0 4px;
}
.connProviderCard {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding: 14px 14px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    text-align: left;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
.connProviderCard:hover {
    background: var(--bg-hover);
    border-color: var(--border-strong);
}
.connProviderCard:active { transform: translateY(1px); }
.connProviderIcon {
    font-size: 20px;
    color: var(--text-secondary);
    margin-bottom: 4px;
}
.connProviderName { font-size: 14px; font-weight: 600; color: var(--text); }
.connProviderSub { font-size: 11.5px; color: var(--text-tertiary); }

/* ── Provider form pane header (back arrow + provider title) ──────── */
.connFormHeader {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0 14px;
}
.connFormBack {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    flex-shrink: 0;
    transition: background var(--transition), color var(--transition);
}
.connFormBack:hover { background: var(--bg-hover); color: var(--text); }
.connFormHeaderText { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.connFormProviderName { font-size: 14px; font-weight: 600; color: var(--text); }
.connFormProviderHelp { font-size: 11.5px; color: var(--text-tertiary); }

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

/* ── Item kebab menu (file row context menu, like Saved) ─────────── */
.storedRowMenuPopover {
    position: fixed;
    z-index: 200;
    min-width: 200px;
    padding: 4px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    display: none;
}
.storedRowMenuPopover[data-open="true"] { display: block; }
.storedRowMenuItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 0;
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition);
}
.storedRowMenuItem:hover { background: var(--bg-hover); }
.storedRowMenuItem--danger { color: #c33; }
.storedRowMenuItem--danger:hover { background: rgba(195, 51, 51, 0.08); }
.storedRowMenuItemIcon { width: 14px; text-align: center; font-size: 12px; color: var(--text-tertiary); flex-shrink: 0; }
.storedRowMenuItem--danger .storedRowMenuItemIcon { color: #c33; }
.storedRowMenuDivider { height: 1px; background: var(--border); margin: 4px 4px; }

/* ── Footer ──────────────────────────────────────────────────────── */
.appFooter {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    background: var(--bg);
    border-top: 1px solid var(--border);
    padding: 16px 24px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 12px;
}

/* ── Confirm modal scaffold (matches Saved/Habits) ───────────────── */
.confirmModal { display: none; position: fixed; inset: 0; z-index: 300; align-items: center; justify-content: center; }
.confirmModal.open { display: flex; }
.confirmModalBackdrop {
    position: absolute; inset: 0;
    background: rgba(20, 20, 20, 0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}
.confirmModalContent {
    position: relative;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.06);
    padding: 22px 22px 18px;
    width: 380px;
    max-width: calc(100% - 32px);
    max-height: calc(100vh - 32px);
    overflow-y: auto;
}
.confirmModalTitle {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: 6px;
    color: var(--text);
}
.confirmModalBody {
    font-size: 13.5px;
    color: var(--text-secondary);
    line-height: 1.5;
    margin-bottom: 16px;
    word-break: break-word;
}
.confirmModalBody strong { color: var(--text); font-weight: 500; }
.confirmModalInput {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.confirmModalInput:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
.confirmModalActions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.confirmModalBtn {
    padding: 7px 14px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.confirmModalBtnCancel { background: transparent; color: var(--text-secondary); border-color: var(--border); }
.confirmModalBtnCancel:hover { background: var(--bg-hover); color: var(--text); }
.confirmModalBtnPrimary { color: #fff; background: var(--accent); }
.confirmModalBtnDanger { color: #fff; background: #c33; }
.confirmModalBtnDanger:hover { background: #b02a2a; }

/* ── Multi-select ──────────────────────────────────────────────────
   Each row carries a checkbox at its leading edge. Hidden by
   default, fades in on row hover OR whenever any rows are
   selected (selection mode), so during bulk picking every row
   shows its checkbox without having to hover. The row itself
   takes a soft accent-soft tint when selected. */
.storedRowCheckbox {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1.5px solid var(--border-strong);
    border-radius: 4px;
    background: var(--bg);
    color: var(--bg-sidebar);
    cursor: pointer;
    font-size: 9px;
    opacity: 0;
    transition: opacity var(--transition), background var(--transition), border-color var(--transition), color var(--transition);
}
.storedRowCheckbox i { opacity: 0; transition: opacity var(--transition); }
.storedRow:hover .storedRowCheckbox,
.storedRowCheckbox.is-checked,
.storedRow.is-selected .storedRowCheckbox { opacity: 1; }
.storedRowCheckbox.is-checked {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--bg-sidebar);
}
.storedRowCheckbox.is-checked i { opacity: 1; }
.storedRowCheckbox:hover { border-color: var(--accent); }
@media (hover: none) { .storedRowCheckbox { opacity: 1; } }
.storedRow.is-selected { background: var(--accent-soft); }
.storedRow.is-selected:hover { background: var(--accent-soft); }

/* Selection toolbar — sits between the breadcrumb and the file
   table whenever any rows are selected. */
.storedSelectionBar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    padding: 8px 12px;
    background: var(--accent-soft);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
/* The UA's [hidden]{display:none} ties on specificity with the
   class rule above, so we have to explicitly defeat it ourselves
   or .hidden gets ignored. Without this, deselecting the last
   row left the toolbar visible reading "1 selected". */
.storedSelectionBar[hidden] { display: none; }
.storedSelectionCount {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}
.storedSelectionLink {
    background: transparent;
    border: 0;
    padding: 4px 8px;
    color: var(--text-secondary);
    font-size: 12.5px;
    cursor: pointer;
    border-radius: var(--radius-sm);
    text-decoration: underline;
    text-underline-offset: 3px;
    transition: background var(--transition), color var(--transition);
}
.storedSelectionLink:hover { color: var(--text); background: var(--bg-hover); }
.storedSelectionSpacer { flex: 1; }
.storedSelectionBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.storedSelectionBtn:hover { background: var(--bg-hover); color: var(--text); border-color: var(--border-strong); }
.storedSelectionBtn--danger { color: #c33; }
.storedSelectionBtn--danger:hover { background: rgba(220, 50, 50, 0.08); color: #c33; }
.storedSelectionBtn--ghost { padding: 6px 8px; color: var(--text-tertiary); border-color: transparent; }
.storedSelectionBtn--ghost:hover { background: var(--bg-hover); color: var(--text); border-color: transparent; }
/* Wraps the action buttons so we can hide them as a group when a
   bulk op is running and the progress display takes over the bar. */
.storedSelectionActions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.storedSelectionActions[hidden] { display: none; }
/* Progress takeover. Sits in the same toolbar slot as the action
   buttons; shown only while a bulk delete/move/copy is in flight.
   The bar grows to fill the toolbar so the readout reads as the
   primary content, not a chip squeezed on the side. */
.storedSelectionProgress {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    min-width: 0;
}
.storedSelectionProgress[hidden] { display: none; }
.storedSelectionProgressSpinner {
    color: var(--text-secondary);
    font-size: 13px;
    flex-shrink: 0;
}
.storedSelectionProgressLabel {
    font-size: 13px;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
.storedSelectionProgressBar {
    flex: 1;
    height: 6px;
    background: var(--bg-sidebar);
    border-radius: 3px;
    overflow: hidden;
    min-width: 80px;
}
.storedSelectionProgressBarFill {
    height: 100%;
    width: 0;
    background: var(--mint);
    border-radius: 3px;
    transition: width 200ms ease;
}
/* Indeterminate state — used when total is unknown. A diagonal
   stripe pattern slides across the bar so the user knows work is
   ongoing even though no per-item count is available. */
.storedSelectionProgressBarFill.is-indeterminate {
    background: linear-gradient(
        90deg,
        var(--mint) 0%,
        var(--mint) 40%,
        rgba(0, 0, 0, 0) 40%,
        rgba(0, 0, 0, 0) 100%
    );
    background-size: 200% 100%;
    animation: storedSelectionIndeterminate 1.1s linear infinite;
}
@keyframes storedSelectionIndeterminate {
    from { background-position: -100% 0; }
    to   { background-position:  100% 0; }
}
/* While busy the count + select-all link are hidden (the readout
   replaces them) — but the bar itself still pulls focus, so the
   cursor stays pointer-default rather than implying clickability. */
.storedSelectionBar.is-busy { cursor: default; }

/* ── Section headers ─────────────────────────────────────────────── */
.storedListSection {
    padding: 8px 14px 6px;
    background: var(--bg-sidebar);
    color: var(--text-tertiary);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border);
}
.storedListSection + .storedRow { border-top: 0; }

/* ── Share modal: list of existing shares + create form ──────────── */
.storedShareList {
    margin: 8px 0 4px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-sidebar);
    max-height: 220px;
    overflow-y: auto;
}
.storedShareEmpty {
    padding: 18px 14px;
    color: var(--text-tertiary);
    font-size: 12.5px;
    text-align: center;
}
.storedShareItem {
    padding: 10px 10px 8px;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
}
.storedShareItem:last-child { border-bottom: 0; }
.storedShareItemRow {
    display: flex;
    align-items: center;
    gap: 6px;
}
.storedShareItemUrl {
    flex: 1;
    min-width: 0;
    padding: 5px 8px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-sidebar);
    color: var(--text);
    font-size: 12px;
    font-family: var(--font-mono);
    outline: none;
}
.storedShareItemUrl:focus { border-color: var(--accent); }
.storedShareCopyBtn,
.storedShareRevokeBtn {
    width: 30px; height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 12px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.storedShareCopyBtn:hover    { color: var(--text); background: var(--bg-hover); border-color: var(--text-tertiary); }
.storedShareCopyBtn.copied   { color: #1f6b3d; border-color: rgba(45, 122, 74, 0.30); }
.storedShareRevokeBtn:hover  { color: #c33; background: rgba(195, 51, 51, 0.08); border-color: rgba(195, 51, 51, 0.30); }
.storedShareItemMeta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-tertiary);
}
.storedShareBadge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-sidebar);
    color: var(--text-secondary);
    font-weight: 500;
}
.storedShareBadge i { font-size: 10px; }
.storedShareBadge--open { color: var(--text-tertiary); }
.storedShareMeta { font-variant-numeric: tabular-nums; }

/* ── Move / Copy folder picker ───────────────────────────────────────
   Lives inside a confirmModalContent--wide. Breadcrumbs at the top,
   scrollable folder list below, Cancel + "Move/Copy here" actions in
   the modal footer (handled by confirmModalActions). */
.storedPickerCrumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    padding: 6px 0;
    margin: 0 0 10px;
    font-size: 13px;
    color: var(--text-secondary);
}
.storedPickerCrumb {
    background: transparent; border: 0;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 13px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.storedPickerCrumb:hover { background: var(--bg-hover); color: var(--text); }
.storedPickerCrumb--current { color: var(--text); font-weight: 500; cursor: default; }
.storedPickerCrumb--current:hover { background: transparent; }
.storedPickerCrumbSep { color: var(--text-tertiary); padding: 0 2px; }

.storedPickerList {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-sidebar);
    max-height: 280px;
    overflow-y: auto;
    margin-bottom: 14px;
}
.storedPickerEmpty {
    padding: 24px 14px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 13px;
    line-height: 1.5;
}
.storedPickerItem {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 14px;
    border: 0;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition);
}
.storedPickerItem:last-child { border-bottom: 0; }
.storedPickerItem:hover { background: var(--bg-hover); }
.storedPickerItemIcon {
    width: 22px; text-align: center;
    color: var(--mint);
    font-size: 15px;
    flex-shrink: 0;
}
.storedPickerItemName {
    flex: 1; min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.storedPickerItemHint {
    font-size: 11.5px;
    color: var(--text-tertiary);
}

/* ── Drag-to-move visual states ──────────────────────────────────────
   File rows being dragged dim. Folder rows being hovered over
   during a drag get a mint inset stripe so the drop target is
   obvious. The window-level "drop external files to upload"
   handler is gated on dataTransfer.types.includes('Files'), which
   internal drags don't carry, so the two flows don't collide. */
.storedRow--dragging { opacity: 0.4; }
.storedRow--dropTarget {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--mint);
}
.storedRow[draggable="true"] { cursor: grab; }
.storedRow[draggable="true"]:active { cursor: grabbing; }

/* ── Rename in-flight ────────────────────────────────────────────────
   While the rename request is round-tripping, the row dims and
   becomes click-inert so the user can't trigger more menu actions
   on a row whose key is about to change. A leading spinner sits in
   front of the name so the affordance is obvious even on a
   long-running folder rename (which copies + deletes every key
   under the prefix). The class is removed when loadList()
   re-renders the listing — or, on error, by the finally block in
   the rename handler. */
.storedRow.is-renaming {
    opacity: 0.55;
    pointer-events: none;
}
.storedRowRenameSpinner {
    color: var(--text-tertiary);
    font-size: 12px;
    margin-right: 6px;
    flex-shrink: 0;
}

/* ── In-app file preview modal ───────────────────────────────────────
   Mirrors the public share viewer's preview surface: image / video /
   audio / pdf inline, "no preview available" card otherwise. Lives
   inside Stored so the user keeps their folder context — close
   returns them to the same listing they came from. */
.storedPreviewModal {
    position: fixed;
    inset: 0;
    z-index: 350;
    display: none;
    align-items: stretch;
    justify-content: stretch;
}
.storedPreviewModal[data-open="true"] { display: flex; }

.storedPreviewBackdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 15, 18, 0.78);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.storedPreviewContent {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    margin: 32px;
    border-radius: var(--radius);
    box-shadow: 0 18px 60px rgba(0, 0, 0, 0.32);
    overflow: hidden;
    max-width: 100%;
}

.storedPreviewHeader {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    flex-shrink: 0;
}
.storedPreviewIdentity {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.storedPreviewName {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.storedPreviewMeta {
    font-size: 11.5px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.storedPreviewActionBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--bg-sidebar);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    border: 0;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    transition: box-shadow 160ms ease, transform 120ms ease;
}
.storedPreviewActionBtn:hover {
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.12);
    transform: translateY(-0.5px);
}
.storedPreviewCloseBtn {
    width: 36px; height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 16px;
    transition: background var(--transition), color var(--transition);
}
.storedPreviewCloseBtn:hover { color: var(--text); background: var(--bg-hover); }

.storedPreviewBody {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: var(--bg-sidebar);
    overflow: auto;
}

.storedPreviewImage,
.storedPreviewVideo,
.storedPreviewAudio,
.storedPreviewPdf {
    display: block;
    max-width: 100%;
    max-height: 100%;
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
    background: var(--bg);
}
.storedPreviewVideo, .storedPreviewPdf { width: 100%; height: 100%; }
.storedPreviewPdf { border: 0; min-height: 480px; }
.storedPreviewAudio {
    width: 100%;
    max-width: 480px;
    box-shadow: none;
    background: transparent;
}

.storedPreviewNone {
    text-align: center;
    padding: 40px 24px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    max-width: 460px;
    width: 100%;
}
.storedPreviewNoneIcon {
    font-size: 36px;
    color: var(--text-tertiary);
    margin-bottom: 12px;
}
.storedPreviewNoneTitle {
    font-size: 15.5px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
    word-break: break-word;
}
.storedPreviewNoneSub {
    font-size: 13px;
    color: var(--text-secondary);
}

@media (max-width: 540px) {
    .storedPreviewContent { margin: 0; border-radius: 0; }
    .storedPreviewMeta { display: none; }
    .storedPreviewActionBtn span { display: none; }
    .storedPreviewActionBtn { padding: 8px 10px; }
}

/* ── Mobile ──────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .storedPage { padding: 16px 12px 120px; }
    .storedListHeader,
    .storedRow {
        grid-template-columns: 1fr 80px 32px;
        padding: 10px 12px;
    }
    /* Hide the date column on small viewports — size + name + menu
       cover the essentials; the kebab still surfaces the timestamp
       via a future "details" item. */
    .storedListHeader > :nth-child(3),
    .storedRow      > :nth-child(3) { display: none; }
    .storedRowMenu { opacity: 1; }
    .formFieldRow { flex-direction: column; gap: 0; }

    /* Stack the connection picker and usage chip across the full
       toolbar width so the bucket name and usage bar both have
       breathing room — at narrow widths the picker's truncated
       label was getting clipped to ~2 words next to the chip. */
    .storedConnectionPicker,
    .storedUsageChip {
        width: 100%;
        flex: 1 1 100%;
        justify-content: flex-start;
    }
    /* On desktop the spacer pushes the action buttons (New folder /
       Upload) to the right edge. Once the toolbar wraps onto
       multiple rows on mobile, that flex:1 spacer claims its own
       row and bakes a blank gap between the usage chip and the
       New folder button. Drop it from the layout below the
       breakpoint. */
    .storedToolbarSpacer { display: none; }
}
