/* ═══════════════════════════════════════════════════════════════════════════════
   browse.css — Enterprise File Browser (CloudAvid File Portal)
   Redesigned per template/browse/code.html, ported into the project's own tokens.

   Token port: every colour and type value here resolves to a token declared in
   tokens.css. No Material-3 names, no CDN fonts, no remote assets — the CSP in
   lib/http-utils.js is `script-src 'self'` / `font-src 'self' data:`.
   See the mapping table at the end of tokens.css.

   ROW STRUCTURE CONTRACT — seven cells, header and rows share one track count:
     [1] c-select  [2] c-icon  [3] c-name  [4] c-type  [5] c-mod  [6] c-size  [7] c-act
   Cells 4-6 (type/modified/size) are the ones hidden responsively, so the
   `nth-child(4|5|6)` rules below address exactly those columns. The six
   pre-existing cells keep their original relative order per the `file-actions`
   capability; the select cell is a new leading cell.

   Keep the desktop action track and the <=640px action track in sync — both are
   the fixed 26px that matches `.f-action { width: 26px }`.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── LAYOUT ROOT ───────────────────────────────────────────────────────── */
.browse-layout {
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
    margin-top: var(--space-lg);
    min-width: 0;
}

/* ── CONTEXT HEADER ────────────────────────────────────────────────────── */
.browse-ctx {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    padding: var(--s5) var(--s6);
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    border: 1px solid var(--border);
}

.browse-title-row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--s4);
    flex-wrap: wrap;
}

.browse-title-left {
    min-width: 0;
    flex: 1;
}

.browse-name-line {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
}

.browse-title-left h1 {
    font-family: var(--font-display);
    font-size: var(--text-headline-lg);
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--text);
    word-break: break-all;
    line-height: 1.2;
    margin: 0;
}

/* Static product chrome only. No code path computes or implies verification —
   see browse-page spec "The signature badge is presentation-only static text". */
.ctx-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px var(--s2);
    border-radius: var(--radius-tags);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    line-height: 1.4;
    white-space: nowrap;
}

.ctx-badge-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-3);
    flex-shrink: 0;
}

.browse-stats {
    display: flex;
    align-items: center;
    gap: var(--s2);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-4);
    margin-top: 6px;
}

.stat-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.stat-item svg {
    color: var(--text-4);
}

.stat-val {
    color: var(--text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.stat-dot {
    color: var(--border-hover);
}

/* ── BREADCRUMBS ───────────────────────────────────────────────────────── */
.crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px;
    font-size: var(--text-label-mono-sm);
}

.crumb {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 11px;
    border-radius: var(--radius-tags);
    color: var(--text-3);
    font-weight: 500;
    transition: color var(--dur-1) ease, background var(--dur-1) ease;
    text-decoration: none;
}

.crumb:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.crumb-active {
    color: var(--text-accent);
    background: var(--glow);
    border: 1px solid var(--border-hover);
    font-weight: 600;
}

.crumb-sep {
    color: var(--text-4);
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

/* The chevron points along the reading direction. */
[dir="rtl"] .crumb-sep svg {
    transform: scaleX(-1);
}

/* ── TOOLBAR ───────────────────────────────────────────────────────────── */
.browse-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-lg);
    background: var(--bg-sunken);
    border: 1px solid var(--border);
}

.browse-search {
    height: 34px;
    padding-inline: 14px 10px;
    border-radius: var(--radius-buttons);
    width: 220px;
    background: var(--bg-card);
    transition: width var(--dur-2) ease, border-color var(--dur-1) ease;
}

.browse-search:focus-within {
    width: 260px;
}

.browse-search input {
    font-size: var(--text-label-code);
}

/* Hint chip — decorative; the real shortcut is bound in browse.js onKeydown(). */
.search-kbd {
    font-family: var(--font-mono);
    font-size: 10px;
    line-height: 1;
    padding: 3px 5px;
    border-radius: var(--radius-sm);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    color: var(--text-3);
    flex-shrink: 0;
}

.browse-chips {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: nowrap;
    overflow-x: auto;
    flex: 1;
    min-width: 0;
    scrollbar-width: none;
}

.browse-chips::-webkit-scrollbar {
    display: none;
}

.chip {
    padding: 5px var(--s3);
    border-radius: var(--radius-tags);
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    line-height: 1.4;
    white-space: nowrap;
    cursor: pointer;
    flex-shrink: 0;
    transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}

.chip:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.chip.active {
    background: var(--glow-strong);
    border-color: var(--border-focus);
    color: var(--text-accent);
    font-weight: 600;
}

.chip-n {
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

.browse-toolbar-right {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-shrink: 0;
}

/* ── BODY GRID — table + inspector ──────────────────────────────────────── */
.browse-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
    align-items: start;
    min-width: 0;
}

/* Wide viewports: the table is FULL WIDTH by default and the inspector track is
   collapsed to 0. Selecting a file expands that track, so the table visibly
   collapses while the card appears beside it.

   Both tracks always exist (1fr + 0px vs 1fr + 340px) because `grid-template-columns`
   can only interpolate between track lists of the SAME length — going from one track
   to two would snap instead of animate. Collapsing the second track to 0 rather than
   removing it is what makes the transition possible at all. */
@media (min-width: 1280px) {
    .browse-body {
        grid-template-columns: minmax(0, 1fr) 0px;
        gap: 0;
        transition: grid-template-columns var(--dur-3) var(--ease), gap var(--dur-3) var(--ease);
    }

    .browse-body.has-inspector {
        grid-template-columns: minmax(0, 1fr) 340px;
        gap: var(--space-lg);
    }

    /* An error state replaces the table, so the inspector track must stay collapsed
       even if a stale `has-inspector` class is present. Declared last so it wins. */
    .browse-body.is-error {
        grid-template-columns: minmax(0, 1fr) 0px;
        gap: 0;
    }
}

/* An error state replaces the table; the empty inspector must not sit beside it. */
.browse-body.is-error {
    grid-template-columns: minmax(0, 1fr);
}

.browse-inspector {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    min-width: 0;
    position: sticky;
    top: calc(var(--nav-h) + var(--space-lg));
}

/* Closed state drives the entrance animation. Only transform and opacity animate,
   so the transition never triggers layout. The card is revealed by adding .is-open
   on a later frame (see file-inspector.js), which is what restarts the animation. */
.browse-inspector[hidden] {
    display: none;
}

.browse-inspector:not(.is-open) {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
    pointer-events: none;
}

.browse-inspector.is-open {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    transition: opacity var(--dur-2) var(--ease), transform var(--dur-3) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
    .browse-inspector {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ── MULTI-SELECT TAB STRIP ─────────────────────────────────────────────── */
/* Sits directly above the metadata section when more than one item is selected.
   Wraps rather than scrolling horizontally so every tab stays reachable in a 340px
   column, and each label truncates instead of stretching the strip. The height cap
   keeps a large selection from pushing the card body out of view. */
.insp-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    max-height: 92px;
    overflow-y: auto;
    padding-bottom: 2px;
    margin-bottom: var(--space-md);
    border-bottom: 1px solid var(--border);
}

.insp-tab {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    max-width: 100%;
    padding: 5px 10px;
    border-radius: var(--radius-tags);
    border: 1px solid var(--border);
    background: var(--bg-sunken);
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    line-height: 1.4;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}

.insp-tab:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.insp-tab:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.insp-tab.is-active {
    background: var(--glow-strong);
    border-color: var(--border-focus);
    color: var(--text-accent);
    font-weight: 600;
}

/* ── METADATA CARD ──────────────────────────────────────────────────────── */
.insp-head {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
}

.insp-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--text-accent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.insp-titles {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

.insp-name {
    font-weight: 600;
    font-size: var(--text-headline-sm);
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.insp-kind {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-3);
}

.insp-close {
    padding: 4px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-3);
    cursor: pointer;
    display: inline-flex;
    flex-shrink: 0;
    transition: background var(--dur-1) ease, color var(--dur-1) ease;
}

.insp-close:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.insp-close:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.insp-actions {
    display: flex;
    flex-direction: column;
    gap: var(--s2);
}

.insp-btn {
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 9px var(--s4);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: var(--text-label-code);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}

.insp-btn:hover:not(:disabled) {
    background: var(--bg-hover);
    color: var(--text);
}

.insp-btn:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.insp-btn-primary {
    background: var(--glow-strong);
    border-color: var(--border-focus);
    color: var(--text-accent);
    font-weight: 600;
}

.insp-btn-ghost {
    background: transparent;
}

.insp-btn:disabled {
    opacity: 0.6;
    cursor: progress;
}

.insp-btn-sub {
    padding-inline-start: 6px;
    opacity: 0.75;
    font-size: var(--text-label-mono-sm);
}

.insp-specs {
    margin: 0;
    display: flex;
    flex-direction: column;
}

.insp-spec {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
    padding: 7px 0;
    border-bottom: 1px solid var(--border);
}

.insp-spec:last-child {
    border-bottom: none;
}

.insp-spec dt {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-3);
    flex-shrink: 0;
}

.insp-spec dd {
    margin: 0;
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text);
    text-align: end;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    font-variant-numeric: tabular-nums;
}

.insp-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.insp-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s2);
}

.insp-section-label {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-3);
}

.insp-copy {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-accent);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    cursor: pointer;
}

.insp-copy:hover {
    background: var(--bg-hover);
}

.insp-copy:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.insp-copy.is-flash {
    color: var(--text-accent);
    border-color: var(--border-focus);
}

.insp-digest-slot {
    min-height: 18px;
}

.insp-digest-row {
    display: flex;
    align-items: flex-start;
    gap: 6px;
}

.insp-digest {
    flex: 1;
    padding: 7px var(--s2);
    border-radius: var(--radius-sm);
    background: var(--bg-sunken);
    border: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text);
    word-break: break-all;
    user-select: all;
    line-height: 1.5;
}

.insp-digest:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.insp-note {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-4);
    padding: 6px 0;
}

.insp-note-busy {
    color: var(--text-3);
}

.insp-note-error {
    color: var(--danger);
}

.insp-snippet {
    padding: 7px var(--s2);
    border-radius: var(--radius-sm);
    background: var(--bg-sunken);
    border: 1px solid var(--border);
    overflow-x: auto;
}

.insp-snippet code {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--info);
    white-space: nowrap;
}

/* The card itself sits on one surface; the inspector column is only its container. */
.browse-inspector > * {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-md);
}

/* The digest/spec lists should not each become their own bordered box. */
.browse-inspector > .insp-specs,
.browse-inspector > .insp-tabs,
.browse-inspector > .insp-section {
    background: transparent;
    border: none;
    padding: 0;
}

.browse-body.is-error .browse-inspector {
    display: none;
}

/* ── FILE TABLE (LIST VIEW) ────────────────────────────────────────────── */
.file-tbl {
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    border: 1px solid var(--border);
    overflow: hidden;
    overflow-x: auto;
    width: 100%;
}

.file-tbl .trow {
    display: grid;
    /* [1]select [2]icon [3]name [4]type [5]modified [6]size [7]action
       Action track is a fixed 26px, matching `.f-action { width: 26px }`. Every .trow is
       its own grid container, so an `auto` action track is content-derived: directory rows
       (empty .f-actions) resolve it to 0px while file rows resolve it to 26px, and the 1fr
       name track absorbs the difference and shifts the fixed columns. Pinning it keeps the
       header and every row on identical column boundaries. Update BOTH this track and the
       one in the <=640px block below, plus .f-action, if the icon size changes. */
    grid-template-columns: 36px 40px minmax(0, 1fr) 90px 160px 90px 26px;
    gap: var(--s3);
    align-items: center;
    min-height: 52px;
    padding: 0 var(--s5);
    border-bottom: 1px solid var(--border);
    transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}

.file-tbl .trow:last-child {
    border-bottom: none;
}

.file-tbl .trow:not(.thead):hover {
    background: var(--bg-hover);
}

/* Keyboard row focus — the rows are tabindex="-1" and driven by onKeydown(). */
.file-tbl .trow:focus-visible,
.file-tbl .trow.is-focused {
    outline: 2px solid var(--border-focus);
    outline-offset: -2px;
    background: var(--bg-hover);
}

.thead {
    min-height: 40px;
    background: var(--bg-sunken);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-4);
}

.thead .c-name {
    cursor: pointer;
}

.thead .c-size {
    text-align: end;
}

/* Responsive hiding target: children 4-6 are exactly type / modified / size. */
.file-tbl .trow>div:nth-child(4),
.file-tbl .trow>div:nth-child(5),
.file-tbl .trow>div:nth-child(6) {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 0;
}

.c-select {
    display: flex;
    align-items: center;
    justify-content: center;
}

.c-select input {
    width: 14px;
    height: 14px;
    accent-color: var(--border-focus);
    cursor: pointer;
}

/* ── ROW ICON ──────────────────────────────────────────────────────────── */
.f-icon {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    flex-shrink: 0;
}

/* Interactive primary target inside the icon cell — same target as the name link.
   Fills the cell, inherits the icon's color/theming, and never changes size or
   position so hover/focus emphasis causes no layout shift. */
.f-icon-link {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: inherit;
    text-decoration: none;
    transition: color var(--dur-1) ease;
}

.f-icon-link:hover,
.f-icon-link:focus-visible {
    color: var(--text-accent);
}

.f-icon-dir {
    background: var(--glow);
    border-color: var(--border-hover);
    color: var(--text-accent);
}

.f-icon-file {
    background: color-mix(in srgb, var(--kind, var(--text-3)) 10%, var(--bg-elevated));
    border-color: color-mix(in srgb, var(--kind, var(--border)) 28%, var(--border));
    color: var(--kind, var(--text-3));
}

/* File-type tint (BrowseIcons.kindOf). Unlisted kinds (text, file) stay neutral. */
[data-kind="archive"] { --kind: #f5b74e; }
[data-kind="disk"]    { --kind: #8fb4ff; }
[data-kind="package"] { --kind: #b49cff; }
[data-kind="code"]    { --kind: #6fd3b5; }
[data-kind="secure"]  { --kind: #86d98f; }
[data-kind="pdf"]     { --kind: #ff8a7a; }
[data-kind="doc"]     { --kind: #7fb0ff; }
[data-kind="sheet"]   { --kind: #6fcf97; }
[data-kind="image"]   { --kind: #f08bd0; }
[data-kind="video"]   { --kind: #ff9f6e; }
[data-kind="audio"]   { --kind: #e3a6ff; }

[data-theme="light"] [data-kind="archive"] { --kind: #a86500; }
[data-theme="light"] [data-kind="disk"]    { --kind: #2f5fbf; }
[data-theme="light"] [data-kind="package"] { --kind: #6a4fc4; }
[data-theme="light"] [data-kind="code"]    { --kind: #11795d; }
[data-theme="light"] [data-kind="secure"]  { --kind: #2d7d3a; }
[data-theme="light"] [data-kind="pdf"]     { --kind: #c0392b; }
[data-theme="light"] [data-kind="doc"]     { --kind: #2b5fb3; }
[data-theme="light"] [data-kind="sheet"]   { --kind: #1f7a45; }
[data-theme="light"] [data-kind="image"]   { --kind: #a83a85; }
[data-theme="light"] [data-kind="video"]   { --kind: #b9541c; }
[data-theme="light"] [data-kind="audio"]   { --kind: #8a3fb0; }

.insp-icon .ficon {
    color: var(--kind, currentColor);
}

/* ── ROW NAME ──────────────────────────────────────────────────────────── */
.f-name {
    min-width: 0;
    /* Essential flex/grid layout fix for text-truncation */
    width: 100%;
    overflow: hidden;
}

.f-link {
    display: block;
    font-weight: 500;
    font-size: var(--text-body-lg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text);
    transition: color var(--dur-1) ease;
    text-decoration: none;
}

.f-link:hover {
    color: var(--text-accent);
}

.f-sub {
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-4);
    font-variant-numeric: tabular-nums;
}

.c-size .f-sub {
    text-align: end;
}

/* ── FILE ACTIONS (per-row action controls, child 7 of .trow) ───────────── */
.f-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 2px;
    white-space: nowrap;
    flex-shrink: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-1) ease;
}

.file-tbl .trow:hover .f-actions,
.file-tbl .trow:focus-within .f-actions {
    opacity: 1;
    pointer-events: auto;
}

@media (hover: none) {
    .f-actions {
        opacity: 1;
        pointer-events: auto;
    }
}

/* Locked rows (admin policy): the sign-in action is always shown, and the row
   cannot be selected, so its checkbox reads as unavailable. */
.file-tbl .trow.is-locked .f-actions {
    opacity: 1;
    pointer-events: auto;
}

.file-tbl .trow.is-locked .row-select {
    cursor: not-allowed;
    opacity: 0.4;
}

.f-action-locked {
    color: var(--warning);
}

/* The name keeps its ellipsis; the Locked chip sits after it and never shrinks. */
.file-tbl .trow.is-locked .f-name {
    display: flex;
    align-items: center;
    gap: 8px;
}

.file-tbl .trow.is-locked .f-name .badge-locked {
    flex-shrink: 0;
}

.f-action {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-tags);
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-4);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}

.f-action:hover {
    background: var(--bg-hover);
    border-color: var(--border);
    color: var(--text);
}

.file-tbl.grid-mode .f-actions {
    justify-content: center;
}

/* ── BULK BAR ───────────────────────────────────────────────────────────── */
/* Lives inside .file-tbl as a table footer, per the design. Hidden (not merely
   emptied) while the selection is empty, so the controls are never reachable with
   nothing to act on. */
.browse-bulkbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    flex-wrap: wrap;
    padding: var(--space-sm) var(--s5);
    border-top: 1px solid var(--border);
    background: var(--bg-sunken);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    color: var(--text-3);
}

.browse-bulkbar[hidden] {
    display: none;
}

.bulk-info {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
    min-width: 0;
}

.bulk-count {
    color: var(--text-accent);
    font-weight: 600;
}

.bulk-dot {
    color: var(--border-hover);
}

.bulk-status:not(:empty) {
    color: var(--text-4);
}

.bulk-status:not(:empty)::before {
    content: "· ";
}

.bulk-actions {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
}

.bulk-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px var(--s3);
    border-radius: var(--radius-tags);
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: var(--text-label-mono-sm);
    cursor: pointer;
    transition: background var(--dur-1) ease, color var(--dur-1) ease,
        border-color var(--dur-1) ease, opacity var(--dur-1) ease;
}

.bulk-btn:hover:not(:disabled) {
    background: var(--bg-hover);
    color: var(--text);
    border-color: var(--border-hover);
}

.bulk-btn:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.bulk-btn-primary {
    background: var(--glow-strong);
    border-color: var(--border-focus);
    color: var(--text-accent);
    font-weight: 600;
}

.bulk-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.bulk-btn.is-flash {
    border-color: var(--border-focus);
    color: var(--text-accent);
}

.browse-bulkbar.is-busy .bulk-btn {
    pointer-events: none;
    opacity: 0.6;
}

/* ── ROW SELECTION ──────────────────────────────────────────────────────── */
.file-tbl .trow.is-selected {
    background: var(--glow);
    box-shadow: inset 3px 0 0 0 var(--border-focus);
}

[dir="rtl"] .file-tbl .trow.is-selected {
    box-shadow: inset -3px 0 0 0 var(--border-focus);
}

.file-tbl .trow.is-selected:hover {
    background: var(--glow-strong);
}

.file-tbl .trow.is-started .f-icon {
    border-color: var(--border-focus);
}

.file-tbl .trow.is-failed .f-icon {
    border-color: var(--danger);
    color: var(--danger);
}

/* ── EMPTY & ERROR STATES (Browse context) ─────────────────────────────── */
/* These were previously inline-styled per instance. They are declared here so the
   states keep the same appearance now that the markup carries no inline style. */
.locked-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-md);
    padding: 64px var(--s6);
    border: 1px solid var(--border);
    border-radius: var(--radius-panels);
    background: var(--bg-card);
}

.locked-icon {
    margin-inline: auto;
    color: var(--text-3);
}

.locked-title {
    font-size: var(--text-heading-sm);
    font-weight: 600;
    color: var(--text);
}

.locked-desc {
    font-size: var(--text-body-lg);
    color: var(--text-4);
    max-width: 400px;
}

.resources-error {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--s8);
    border-radius: var(--radius-md);
    color: var(--text-3);
}

.resources-error.is-notfound {
    flex-direction: column;
    text-align: center;
    padding: 64px var(--s6);
    border: 1px dashed var(--border);
    background: var(--bg-card);
}

.err-code {
    font-family: var(--font-mono);
    font-size: 48px;
    font-weight: 900;
    color: var(--danger);
    line-height: 1;
}

.err-title {
    font-size: var(--text-heading-sm);
    font-weight: 600;
    color: var(--text);
}

.err-desc {
    font-size: var(--text-body-lg);
    color: var(--text-4);
    max-width: 400px;
}

.err-desc .mono {
    display: inline-block;
    margin-top: 8px;
    padding: 2px 6px;
    background: var(--glow);
    border-radius: var(--radius-sm);
    color: var(--text-accent);
}

.err-inline {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: start;
}

.err-inline-title {
    font-weight: 600;
    color: var(--text);
}

.err-inline-sub {
    font-size: var(--text-label-code);
    color: var(--text-4);
    margin-top: 4px;
}

.empty-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s3);
    padding: 48px var(--s5);
    text-align: center;
}

.empty-circle {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--text-4);
}

.empty-circle.err {
    background: rgba(239, 68, 68, 0.08);
    border-color: rgba(239, 68, 68, 0.25);
    color: var(--danger);
}

.empty-text {
    font-size: var(--text-body-lg);
    color: var(--text-3);
    line-height: 1.5;
}

.empty-text strong {
    display: block;
    color: var(--text);
    font-size: var(--text-body);
    margin-bottom: 2px;
}

/* ── FILE GRID MODE (CARDS VIEW) ───────────────────────────────────────── */
.file-tbl.grid-mode .thead {
    display: none;
}

.file-tbl.grid-mode #rows {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--s3);
    padding: var(--s4);
}

.file-tbl.grid-mode .trow {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    min-height: 0;
    padding: var(--s5) var(--s3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    gap: var(--s2);
    position: relative;
}

.file-tbl.grid-mode .trow:hover {
    border-color: var(--border-hover);
    background: var(--bg-hover);
}

/* In card mode the select control moves to the card's inline-start corner so it
   does not consume a flex row of its own. */
.file-tbl.grid-mode .c-select {
    position: absolute;
    inset-block-start: 8px;
    inset-inline-start: 8px;
}

.file-tbl.grid-mode .f-icon {
    width: 40px;
    height: 40px;
    margin-bottom: 4px;
}

.file-tbl.grid-mode .f-icon .ficon {
    width: 24px;
    height: 24px;
}

.file-tbl.grid-mode .f-name {
    width: 100%;
    max-width: 100%;
    padding: 0 4px;
}

/* Grid View Truncation: max 2 lines with break-word fallback */
.file-tbl.grid-mode .f-link {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
    word-break: break-all;
    overflow-wrap: anywhere;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.4;
    max-height: 2.8em;
    text-align: center;
}

.file-tbl.grid-mode .trow>div:nth-child(4),
.file-tbl.grid-mode .trow>div:nth-child(5),
.file-tbl.grid-mode .trow>div:nth-child(6) {
    display: none;
}

/* ── RESPONSIVE ────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .browse-search,
    .browse-search:focus-within {
        width: 100%;
    }

    .browse-search {
        order: -1;
    }

    .browse-chips {
        order: 0;
        width: 100%;
        flex: 1 0 100%;
    }

    .browse-toolbar-right {
        width: 100%;
        justify-content: space-between;
    }
}

@media (max-width: 640px) {
    .browse-ctx {
        padding: var(--s4);
    }

    .browse-title-row {
        flex-direction: column;
        align-items: stretch;
    }

    .file-tbl .trow {
        /* [1]select [2]icon [3]name [7]action. Keep in sync with the desktop action
           track above: 26px == `.f-action { width: 26px }`. */
        grid-template-columns: 32px 36px minmax(0, 1fr) 26px;
        gap: var(--s2);
        min-height: 0;
        padding: 10px var(--s3);
    }

    .file-tbl .trow>div:nth-child(4),
    .file-tbl .trow>div:nth-child(5),
    .file-tbl .trow>div:nth-child(6) {
        display: none;
    }

    .thead {
        display: none;
    }

    .browse-title-left h1 {
        font-size: var(--text-headline-sm);
    }
}
/* ── CARD ZIP ACTION ───────────────────────────────────────────────────── */
/* Actions rise in one after another as the card opens. */
.browse-inspector.is-open .insp-actions > * {
    animation: fadeUp 280ms var(--ease) both;
}

.browse-inspector.is-open .insp-actions > :nth-child(2) {
    animation-delay: 70ms;
}

.insp-btn svg {
    transition: transform var(--dur-2) var(--ease);
}

.insp-btn:hover:not(:disabled) svg {
    transform: translateY(2px);
}

.insp-btn:active:not(:disabled) {
    transform: scale(0.98);
}

.insp-zip.is-busy svg {
    animation: insp-zip-drop 700ms var(--ease) infinite;
}

@keyframes insp-zip-drop {
    0%   { transform: translateY(-3px); opacity: 0.4; }
    60%  { transform: translateY(2px);  opacity: 1; }
    100% { transform: translateY(2px);  opacity: 0.4; }
}
