Files
bwf-analyser/build/tauri-shell.css
T
Vincent 16c3e6e103 Drop the browser build; space works the transport; fix bulk track rename
The browser page is gone, with its shim, its shell CSS and its suite. build.py
has no --tauri flag and one output: the app's page. The patch lists lose the
SHARED_ prefix, which only ever meant "shared between the two builds", and
test-pdf.js was quietly loading the browser page — it reads the app's now.

Space plays and pauses, in the main window off the player at the bottom and in
the mixer off the same transport. It is swallowed rather than passed on: that
stops the window scrolling, and stops a focused button taking the same press as
a second activation, which toggles twice and looks like a dead key. Typing, and
any dialog other than the mixer, keep it. Deciding what is in front needs both
markers — closing does not always remove .open, and .modal without it is
display:none regardless of the hidden attribute.

The mixer footer put the next file's name adrift in the middle of the row. The
margin-left: auto meant to park it beside Close could do nothing, because the
framework's flex: 1 1 auto had both nav groups growing to fill the row and left
no free space to absorb. Pinned to flex: 0 0 auto. The file-detail modal shares
the markup and follows.

Bulk track rename wrote nothing, on every file, and had never worked. A rename
is keyed on the name it replaces rather than a path, so the frame-rate pass
threw reading edit.path off it — before any byte was written, so nothing was
corrupted, only untouched. The failure handler discarded the reason and the run
still ended on a tidy Done, which is why 0 saved read as progress; it now names
the file and the cause in the log.

429 checks. The gap that hid the rename bug was end-to-end: the writer was unit
tested and the panel rendered, and nothing drove one into the other.
2026-08-18 00:14:36 +08:00

862 lines
25 KiB
CSS

/* ---------------------------------------------------------------
Native app shell.
In a window of its own there's no page to sit on, so the card
chrome, the outer margin and the grey backdrop all go: the app is
the window. The read-only entry points go too — this build opens
folders read-write and nothing else.
--------------------------------------------------------------- */
html {
-webkit-text-size-adjust: 100%;
height: 100%;
}
body {
margin: 0;
padding: 0;
height: 100%;
background: var(--color-bg);
color: var(--color-text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 15px;
line-height: 1.5;
/* The window itself is the scroll container; nothing here should
ever produce a horizontal one. */
overflow-x: hidden;
}
.page {
max-width: none;
margin: 0;
padding: 0;
min-height: 100%;
}
.bwfa-scope.bwfa-app {
background: var(--color-bg);
border: 0;
border-radius: 0;
box-shadow: none;
/* The plugin caps itself at --container-lg (960px) and centres inside
that, which is right for a page in a theme and wrong for a window:
widen the window past 960 and the extra space just sat there. In an
app the window IS the container, so the cap goes and the padding
below becomes the only gutter. */
max-width: none;
width: 100%;
margin-inline: 0;
padding: 18px 20px 28px;
min-height: 100%;
box-sizing: border-box;
}
/* Read-only selection is gone, and so is the in-app title: the window
already says what this is, and the privacy note was written for a
web page. The markup stays put — the analyser wires listeners to
these nodes at startup and the bridge still hands files back through
the inputs inside them — it just isn't shown. */
.bwfa-scope .bwfa-header,
.bwfa-scope .bwfa-dropzone,
.bwfa-scope .bwfa-edit-divider {
display: none !important;
}
/* Which promotes the editor to the main event. */
.bwfa-scope .bwfa-edit-entry {
margin: 0 0 18px;
padding: 18px 20px;
border: 1px dashed var(--color-border);
border-radius: 10px;
background: var(--color-surface);
text-align: center;
transition: border-color .12s ease, background-color .12s ease;
}
.bwfa-scope .bwfa-edit-entry.is-dragover {
border-color: var(--color-info);
border-style: solid;
background: var(--color-info-bg);
}
.bwfa-scope .bwfa-edit-entry .btn {
font-size: 15px;
padding: 9px 20px;
}
.bwfa-scope .bwfa-edit-entry .bwfa-dropzone-subnote {
max-width: 62ch;
margin: 12px auto 0;
font-size: 12.5px;
color: var(--color-text-muted);
}
/* Header sits tighter now that it's a title bar rather than a page
heading. */
.bwfa-scope .bwfa-header {
margin-bottom: 14px;
}
.bwfa-scope .bwfa-title {
font-size: 19px;
margin: 0 0 4px;
}
/* Let the table use the full width of the window. */
.bwfa-scope .table-responsive {
width: 100%;
overflow-x: auto;
}
.bwfa-scope .bwfa-table {
width: 100%;
}
/* Keep both action columns tight; the rest of the width belongs to
the metadata. */
.bwfa-scope .bwfa-table thead th:nth-child(1),
.bwfa-scope .bwfa-table thead th:nth-child(2) {
width: 1%;
white-space: nowrap;
}
/* ---- Sticky table header ------------------------------------------
Two things in the framework break `position: sticky` on a table
header in WebKit specifically, and both were in play:
- `border-collapse: collapse`. Collapsed borders belong to the
table grid rather than to the cells, and Safari has never
painted a sticky header correctly through one — rows bleed over
the header and its underline detaches. `separate` with zero
spacing looks identical and behaves.
- `-webkit-overflow-scrolling: touch` on the scroll container.
It hands scrolling to a separate compositing layer, which is a
long-standing way to get stale pixels and sticky elements that
scroll away. Momentum scrolling is the platform's job on macOS
anyway.
------------------------------------------------------------------ */
.bwfa-scope .table-responsive {
-webkit-overflow-scrolling: auto;
}
.bwfa-scope .bwfa-table {
border-collapse: separate;
border-spacing: 0;
}
/* Collapse was what drew the row lines; with separate borders each cell
draws its own, which comes to the same thing visually. */
.bwfa-scope .bwfa-table th,
.bwfa-scope .bwfa-table td {
border-bottom: 1px solid var(--color-border);
}
/*
* Both selectors, deliberately. The plugin gives every *sortable* header
* `position: relative` (for the sort arrow), and
* `.bwfa-table th[data-bwfa-sort]` outranks `.bwfa-table thead th` — so
* naming only the second left fourteen of seventeen headers relative
* rather than sticky. The three that held were the ones that aren't
* sortable: the two action columns, Description and Note. Hence a header
* that was half stuck and half scrolling, with rows painting through the
* gap.
*
* Sticky is itself a positioned value, so the absolutely-positioned sort
* arrow still anchors to its own cell.
*/
.bwfa-scope .bwfa-table thead th,
.bwfa-scope .bwfa-table thead th[data-bwfa-sort] {
position: sticky;
top: 0;
/* Above the rows, which are unpositioned, and above the row
backgrounds that were painting over it. */
z-index: 3;
background: var(--color-bg);
background-clip: padding-box;
}
/* Nothing in the body may promote itself above the header. */
.bwfa-scope .bwfa-table tbody td {
position: static;
z-index: auto;
}
@media (max-width: 700px) {
.bwfa-scope.bwfa-app {
padding: 12px 12px 20px;
}
}
/* ---- Toolbar ------------------------------------------------------
The window's minWidth is set so this row always fits; nowrap makes
that a hard guarantee rather than a hope, and keeps the search field
as the only thing that gives.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-toolbar {
flex-wrap: nowrap;
align-items: center;
gap: 12px;
}
.bwfa-scope .bwfa-search-group {
flex: 1 1 auto;
min-width: 180px;
margin-bottom: 0;
}
.bwfa-scope .bwfa-export-actions {
flex: none;
flex-wrap: nowrap;
}
.bwfa-scope .bwfa-export-actions .btn,
.bwfa-scope .bwfa-toolbar .btn {
white-space: nowrap;
}
/* ---- Selection ----------------------------------------------------
This is an app, not a document: dragging a selection across a table
of takes only ever looks like a mistake. Fields you type into keep
selection, since editing without it is miserable.
------------------------------------------------------------------ */
.bwfa-scope,
body {
-webkit-user-select: none;
user-select: none;
}
.bwfa-scope input,
.bwfa-scope textarea,
.bwfa-scope select,
.bwfa-scope [contenteditable="true"] {
-webkit-user-select: text;
user-select: text;
}
/* ---- The folder bar, once a folder is open -------------------------
Before: a dashed panel inviting you to open something. After: one
line saying which folder you're in, with the button to change it.
The invitation has served its purpose and the table needs the room.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-edit-entry.is-folder-open {
display: flex;
align-items: center;
gap: 12px;
margin: 0 0 14px;
padding: 0;
border: 0;
background: none;
text-align: left;
}
.bwfa-scope .bwfa-edit-entry.is-folder-open .bwfa-dropzone-subnote {
display: none;
}
.bwfa-scope .bwfa-edit-entry.is-folder-open .btn {
font-size: var(--fs-sm);
padding: 6px 14px;
}
.bwfa-scope .bwfa-current-folder {
font-size: 15px;
font-weight: var(--fw-medium);
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bwfa-scope .bwfa-current-folder::before {
content: "";
display: inline-block;
width: 13px;
height: 11px;
margin-right: 8px;
vertical-align: -1px;
background-color: var(--color-text-muted);
-webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M1 2.5A1.5 1.5 0 0 1 2.5 1h2.2c.4 0 .8.2 1 .5l.7.9h5.1A1.5 1.5 0 0 1 13 3.9v5.6A1.5 1.5 0 0 1 11.5 11h-9A1.5 1.5 0 0 1 1 9.5v-7Z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M1 2.5A1.5 1.5 0 0 1 2.5 1h2.2c.4 0 .8.2 1 .5l.7.9h5.1A1.5 1.5 0 0 1 13 3.9v5.6A1.5 1.5 0 0 1 11.5 11h-9A1.5 1.5 0 0 1 1 9.5v-7Z'/%3E%3C/svg%3E");
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
}
/* ---- Window layout: the table is the only thing that scrolls -------
The player has to stay put while a long day scrolls past it. Pinning
it with position:fixed and reserving page padding didn't hold up —
the plugin sets .table-responsive to overflow-y:hidden, so the table
never scrolls itself and the window does, which puts the last rows
under a fixed footer no matter how much padding is reserved.
So the layout is explicit instead: the app is a column exactly as
tall as the window, the table region is the one scrolling box, and
the player is an ordinary block ordered after it. There is no
clearance to get wrong, because the scrolling box ends where the
player begins. The sticky table header now sticks to the top of that
box, which is also what you want.
------------------------------------------------------------------ */
html,
body {
height: 100%;
overflow: hidden;
}
.page {
height: 100%;
min-height: 0;
}
.bwfa-scope.bwfa-app {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
padding-bottom: 14px;
}
.bwfa-scope .bwfa-results {
display: flex;
flex-direction: column;
flex: 1 1 auto;
min-height: 0;
margin-top: 0;
}
.bwfa-scope .bwfa-results > .table-responsive {
flex: 1 1 auto;
min-height: 0;
overflow-x: auto;
overflow-y: auto;
}
/* Ordered last regardless of where it sits in the markup. */
.bwfa-scope .bwfa-player {
order: 99;
flex: none;
margin: 12px 0 0;
padding: 10px 14px 12px;
gap: 8px;
}
.bwfa-scope .bwfa-player-waveform {
height: 34px;
}
/* The plugin spaced the status line by giving the results panel a top
margin; making that panel a flex child meant zeroing it, which left
"Done — 35 files analysed" sitting on top of the search field. The
status carries its own spacing now, and keeps its min-height so the
layout doesn't jump when the line appears. */
.bwfa-scope .bwfa-status {
margin: 6px 0 14px;
}
/* ---- Launch state --------------------------------------------------
With nothing open there's nothing to report, so the status line and
the "No files analysed yet" placeholder are noise. What's left is one
panel, centred, which is the only thing there is to do.
------------------------------------------------------------------ */
.bwfa-scope.bwfa-app:not(.has-folder) {
justify-content: center;
}
.bwfa-scope.bwfa-app:not(.has-folder) .bwfa-status,
.bwfa-scope.bwfa-app:not(.has-folder) .bwfa-empty {
display: none;
}
.bwfa-scope.bwfa-app:not(.has-folder) .bwfa-edit-entry {
max-width: 560px;
margin: 0 auto;
padding: 32px 28px;
}
/* The app's own icon, inlined at build time from the .icns source set so
the frontend stays a single self-contained file. Launch screen only —
once you're working, the window's title bar and Dock icon are enough. */
.bwfa-scope .bwfa-launch-logo {
display: none;
}
.bwfa-scope.bwfa-app:not(.has-folder) .bwfa-launch-logo {
display: block;
width: 88px;
height: 88px;
margin: 0 auto 22px;
background-image: url("@@LAUNCH_LOGO@@");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
/* Every folder this build opens is opened read-write, so a banner saying
so on every screen is telling you something you can't change and
already know. The warning that matters is on the launch panel, where
you choose the folder in the first place. */
.bwfa-scope .bwfa-editing-note {
display: none !important;
}
/* ---- Bulk edit and export live in modals ---------------------------
Both panels used to open as siblings of the table inside a column
exactly as tall as the window. The table region is the flexible one
(`min-height: 0`, so it may shrink to nothing), so a panel at its
natural height squeezed the table out of existence — and since the
window itself doesn't scroll, that left nothing scrollable anywhere.
Capping the panel and flooring the table held, but only by dividing a
space neither of them wanted to share.
As modals they're out of that fight: the dialog is positioned against
the viewport and scrolls itself, and the table keeps the whole column.
The panel inside gives up its own card — the dialog is the card now.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-sheet-dialog {
position: relative;
/* Width and height come from --modal-width with every other modal's.
Setting them here is how the sheets ended up a different size from
the rest, twice. */
}
.bwfa-scope .bwfa-sheet-wide {
max-width: 1120px;
}
/* Padding comes from --modal-pad with every other modal's. This file is
loaded after overrides.css, so anything set here silently beats the
shared rules — which is how Bulk Edit ended up with this panel's 24px
on top of the shared header's 32px while Sound Report had only the 32.
Three rounds of "why is that one different" traced back to here. */
/* The close button is a traffic light now, styled once for every modal in
overrides.css. This rule used to pin it top right with padding of its
own, which quietly made the sheets' button a different size and place
from everything else's — it loaded after the shared rule and won. */
.bwfa-scope .bwfa-sheet-close {
z-index: 2;
}
/* Room for the close button, so a long heading can't run under it. */
/* Header padding comes from --modal-pad with every other modal's. */
.bwfa-scope .bwfa-results > .table-responsive {
min-height: 20vh;
}
/* ---- Reset ---------------------------------------------------------
Sits left of the folder button and undoes the session: closes the
folder, empties the table, forgets what to reopen. Only meaningful
once something is open, so that's the only time it's there.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-reset {
display: none;
}
.bwfa-scope .bwfa-edit-entry.is-folder-open .bwfa-reset {
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
width: 30px;
height: 30px;
padding: 0;
font-size: 0;
border-radius: 50%;
}
.bwfa-scope .bwfa-reset::before {
content: "";
display: block;
width: 13px;
height: 13px;
background-color: currentColor;
-webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 2.5 14.2 10.2H1.8z' fill='black'/%3E%3Crect x='1.8' y='11.9' width='12.4' height='2.1' rx='.7' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 2.5 14.2 10.2H1.8z' fill='black'/%3E%3Crect x='1.8' y='11.9' width='12.4' height='2.1' rx='.7' fill='black'/%3E%3C/svg%3E");
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: contain;
mask-size: contain;
}
/* ---- Export panel --------------------------------------------------
Wears the bulk-edit panel's classes, so the card, the 38px control
height, the label treatment and the 40vh cap all come for free. Only
the parts it doesn't share are here: the destination row, which is a
field with a button welded to its end, and the report.
------------------------------------------------------------------ */
/* Its own row class rather than the bulk-edit one: the app enumerates
.bwfa-bulk-edit-row to work out which fields to write, so sharing the
name would hand it five controls that have nothing to do with editing.
The look is shared here instead, which is the part worth sharing. */
.bwfa-scope .bwfa-export-fields {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 16px 20px;
margin-bottom: var(--space-4);
max-width: 1080px;
align-items: start;
}
.bwfa-scope .bwfa-export-row {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
.bwfa-scope .bwfa-export-row > .form-label {
min-width: 0;
margin: 0;
color: var(--color-text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.bwfa-scope .bwfa-export-row > .form-control,
.bwfa-scope .bwfa-export-row > .form-select {
width: 100%;
height: 38px;
min-height: 38px;
padding: 0 10px;
line-height: 1.2;
box-sizing: border-box;
font-size: var(--fs-sm);
}
.bwfa-scope .bwfa-export-row > .form-select {
-webkit-appearance: none;
appearance: none;
padding-right: 30px;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%2371717a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 11px center;
background-size: 11px;
}
.bwfa-scope .bwfa-export-row input[type="number"] {
-moz-appearance: textfield;
}
.bwfa-scope .bwfa-export-row input[type="number"]::-webkit-outer-spin-button,
.bwfa-scope .bwfa-export-row input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Nothing to type into means nothing to look at: a disabled target reads
as inactive rather than as a field you're failing to fill in. */
.bwfa-scope .bwfa-export-row > .form-control:disabled {
background-color: var(--color-surface-alt, #f4f4f5);
color: var(--color-text-muted);
}
/* The path is the long one, so it gets the width when there is any. */
.bwfa-scope .bwfa-export-dest {
grid-column: span 2;
min-width: 0;
}
.bwfa-scope .bwfa-export-dest-row {
display: flex;
gap: 8px;
align-items: stretch;
min-width: 0;
}
.bwfa-scope .bwfa-export-dest-row > .form-control {
flex: 1 1 auto;
min-width: 0;
height: 38px;
padding: 0 10px;
font-size: var(--fs-sm);
box-sizing: border-box;
direction: ltr;
/* A long path should show its end — the folder — not its beginning. */
text-overflow: ellipsis;
}
.bwfa-scope .bwfa-export-dest-row > .btn {
flex: none;
height: 38px;
padding: 0 14px;
white-space: nowrap;
}
/* ---- The report modal ----------------------------------------------
A finished export is not a form, so it stops looking like one. The
dialog is the only one that doesn't scroll as a whole: the heading,
the counts and the buttons stay put and the list moves under them,
which is the difference between reading a hundred rows and hunting
for the button that dismisses them.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-sheet-report {
display: flex;
flex-direction: column;
overflow: hidden;
/* Width comes from --modal-width with every other modal's. This used
to set its own, which is exactly how six dialogs ended up six
different sizes. */
}
.bwfa-scope .bwfa-sheet-report .bwfa-result-panel {
display: flex;
flex-direction: column;
min-height: 0;
flex: 1 1 auto;
}
.bwfa-scope .bwfa-result-panel .bwfa-bulk-edit-header {
margin-bottom: var(--space-4);
}
.bwfa-scope .bwfa-result-panel .bwfa-bulk-edit-header p {
margin: 4px 0 0;
font-size: var(--fs-sm);
color: var(--color-text-muted);
word-break: break-all;
}
.bwfa-scope .bwfa-result-tally {
display: flex;
gap: var(--space-5);
flex: none;
padding-bottom: var(--space-4);
border-bottom: 1px solid var(--color-border);
}
.bwfa-scope .bwfa-result-stat {
display: flex;
flex-direction: column;
gap: 1px;
line-height: 1.15;
}
.bwfa-scope .bwfa-result-stat strong {
font-size: 22px;
font-weight: var(--fw-semibold);
font-variant-numeric: tabular-nums;
color: var(--color-text);
}
.bwfa-scope .bwfa-result-stat span {
font-size: var(--fs-xs, 12px);
color: var(--color-text-muted);
}
/* A count of nothing still belongs on screen — "0 failed" is the whole
reassurance — but it shouldn't compete with the counts that matter. */
.bwfa-scope .bwfa-result-stat.is-zero strong,
.bwfa-scope .bwfa-result-stat.is-zero span {
color: var(--gray-400, #b0b0b8);
}
.bwfa-scope .bwfa-result-stat.is-bad strong {
color: var(--color-danger, #b42318);
}
.bwfa-scope .bwfa-result-note {
flex: none;
margin: var(--space-3) 0 0;
font-size: var(--fs-sm);
color: var(--color-text-muted);
}
.bwfa-scope .bwfa-result-panel .bwfa-bulk-edit-actions {
flex: none;
margin-top: var(--space-4);
padding-top: var(--space-4);
border-top: 1px solid var(--color-border);
}
.bwfa-scope .bwfa-export-report {
margin-top: var(--space-3);
font-size: var(--fs-sm);
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
/* Room for the scrollbar so the last column doesn't sit under it. */
padding-right: 4px;
}
.bwfa-scope .bwfa-export-report ul {
margin: 0;
padding: 0;
list-style: none;
}
.bwfa-scope .bwfa-export-report li {
display: flex;
gap: 16px;
padding: 7px 2px;
color: var(--color-text-muted);
border-bottom: 1px solid var(--color-border-subtle, var(--gray-100, #f1f1f4));
}
.bwfa-scope .bwfa-export-report li:last-child {
border-bottom: 0;
}
.bwfa-scope .bwfa-export-report li.is-problem {
color: var(--color-danger, #b42318);
}
.bwfa-scope .bwfa-export-report-name {
flex: none;
width: 38%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--color-text);
font-variant-numeric: tabular-nums;
}
.bwfa-scope .bwfa-export-report-detail {
flex: 1 1 auto;
min-width: 0;
}
/* ---- Track picker in the export panel ------------------------------
The same chips as the player's channel strip, because they answer
the same question about the same file — there they mute, here they
choose what gets written. Only offered for a single file: across a
folder of takes, "track 3" isn't the same thing twice.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-export-tracks {
grid-column: 1 / -1;
}
.bwfa-scope .bwfa-export-tracks .bwfa-channel-chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 4px 0;
}
.bwfa-scope .bwfa-export-tracks .chip {
cursor: pointer;
user-select: none;
}
/* Off reads as off: struck through and faded, the way a muted channel
already reads in the player. */
.bwfa-scope .bwfa-export-tracks .chip.is-off {
opacity: 0.45;
text-decoration: line-through;
}
/* ---- The audio escape hatch ----------------------------------------
Only in the app, where reloading the window costs a folder re-scan
and nothing else: the last folder reopens by itself.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-settings-action {
display: block;
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid var(--color-border);
}
/* ---- What a combine would make ------------------------------------
Shown before anything is written, because the answer to "can this be
done" is already in the metadata: rates, timecodes, lengths. A
problem here disables Export rather than interrupting with a dialog.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-export-summary-line {
margin: 4px 0 14px;
padding: 10px 12px;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm, 6px);
background-color: var(--color-surface);
font-size: var(--fs-sm);
color: var(--color-text);
}
.bwfa-scope .bwfa-export-summary-line.is-blocked {
border-color: var(--color-danger);
background-color: var(--color-danger-bg);
color: var(--color-danger);
}
.bwfa-scope .bwfa-export-summary-line small {
display: block;
margin-top: 4px;
color: var(--color-text-muted);
}
.bwfa-scope .bwfa-export-summary-line.is-blocked small {
color: inherit;
}
/* ---- Naming the copies ---------------------------------------------
The pattern row and the preview both span, because a filename is a
long thing and reading old against new is the entire point of
showing it at all.
------------------------------------------------------------------ */
.bwfa-scope .bwfa-export-pattern {
grid-column: 1 / -1;
min-width: 0;
}
.bwfa-scope .bwfa-export-tokens {
margin: 6px 0 0;
font-size: var(--fs-xs, 12px);
color: var(--color-text-muted);
font-variant-numeric: tabular-nums;
word-spacing: 4px;
}
.bwfa-scope .bwfa-export-names {
margin: 4px 0 12px;
padding: 10px 12px;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm, 6px);
background-color: var(--color-surface);
font-size: var(--fs-sm);
color: var(--color-text-muted);
}
.bwfa-scope .bwfa-export-names.is-blocked {
border-color: var(--color-danger);
background-color: var(--color-danger-bg);
color: var(--color-danger);
}
.bwfa-scope .bwfa-export-name-row {
display: flex;
align-items: baseline;
gap: 10px;
padding: 2px 0;
min-width: 0;
}
/* The arrow is drawn rather than typed, so a name containing one can't
be mistaken for the thing pointing at it. */
.bwfa-scope .bwfa-export-name-row > span::after {
content: "\2192";
margin-left: 10px;
color: var(--color-text-muted);
}
.bwfa-scope .bwfa-export-name-row > span {
flex: none;
max-width: 46%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bwfa-scope .bwfa-export-name-row > strong {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: var(--fw-medium, 500);
color: var(--color-text);
}
.bwfa-scope .bwfa-export-names small {
display: block;
margin-top: 4px;
}