/* =============================================================================
   MarkSwift — design system

   Graphite surfaces, one electric blue accent.

   The previous UI expressed everything through colour: a two-stop gradient on
   every button, glass on every panel, and three traffic-light hues for what are
   really just three speed settings. Nothing was ranked, so nothing read as
   important. Here the accent is the only saturated colour on screen, and it is
   spent deliberately — primary action, active tab, selection, focus. Structure
   comes from crisp hairlines and tight elevation instead.

   Structure:
     1. Tokens
     2. Base
     3. Components
     4. Layout mechanics (split pane)
     5. Document preview
     6. Mobile file sheet
     7. Scrollbars
     8. Responsive & preference queries

   Every foreground/background pair below was checked against WCAG AA before
   being committed; body and secondary text clear 4.5:1 on every surface they
   are used on, in both themes.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
    --surface: #f7f8fa;
    --surface-raised: #ffffff;
    --surface-sunken: #eef0f4;

    --border: #e3e6ea;
    --border-strong: #cfd4db;

    /* Segmented control gets its own pair rather than reusing surface tokens.
       Elevation runs in opposite directions per theme — a raised pill is
       lighter than its track in light mode and also lighter in dark mode, but
       "sunken" and "raised" swap roles between the two, so sharing tokens with
       hover backgrounds made the selected pill read as pressed-in on dark. */
    --control-track: #eef0f4;
    --control-selected: #ffffff;

    --text: #0d1117;
    --text-secondary: #4a5260;
    --text-muted: #79818f;

    /* One accent. `--accent` is for text, icons and borders; `--accent-solid`
       is for filled surfaces. They differ in dark mode, where a fill light
       enough to read as blue would not carry white type. */
    --accent: #2563eb;
    --accent-hover: #1d4ed8;
    --accent-solid: #2563eb;
    --accent-solid-hover: #1d4ed8;
    --accent-weak: #eff4ff;
    --accent-border: #bfd3fe;
    --accent-ring: rgba(37, 99, 235, 0.32);
    --on-accent: #ffffff;

    --danger: #c2321f;
    --danger-weak: #fdf0ee;
    --danger-border: #f5cdc6;
    --success: #047857;
    --success-weak: #ecfaf4;
    --success-border: #b7e6d3;

    --radius-sm: 5px;
    --radius-md: 7px;
    --radius-lg: 10px;

    /* Offset + soft blur, never a zero-offset halo. */
    --shadow-sm: 0 1px 2px rgba(13, 17, 23, 0.05), 0 1px 3px rgba(13, 17, 23, 0.07);
    --shadow-md: 0 2px 4px -1px rgba(13, 17, 23, 0.05), 0 6px 16px -4px rgba(13, 17, 23, 0.12);
    --shadow-lg: 0 8px 24px -6px rgba(13, 17, 23, 0.16), 0 2px 6px -2px rgba(13, 17, 23, 0.08);

    --dur: 130ms;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);

    --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Code",
        "Roboto Mono", Consolas, "Liberation Mono", Menlo, monospace;
}

.dark {
    --surface: #0b0d10;
    --surface-raised: #14171c;
    --surface-sunken: #1b1f26;

    --border: #232830;
    --border-strong: #333a45;

    /* Pill is lighter than its track, matching how elevation reads on dark.
       #232830 rather than something lighter so the accent label still clears
       4.5:1 against it. */
    --control-track: #14171c;
    --control-selected: #232830;

    --text: #f2f4f7;
    --text-secondary: #a8b1c0;
    --text-muted: #7b8494;

    --accent: #4d8dff;
    --accent-hover: #6ba0ff;
    --accent-solid: #2b62d6;
    --accent-solid-hover: #3572e8;
    --accent-weak: #12203a;
    --accent-border: #26436f;
    --accent-ring: rgba(77, 141, 255, 0.38);
    --on-accent: #ffffff;

    --danger: #f87171;
    --danger-weak: #251518;
    --danger-border: #4a2326;
    --success: #34d399;
    --success-weak: #0e2620;
    --success-border: #1d4438;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 2px 4px -1px rgba(0, 0, 0, 0.4), 0 6px 16px -4px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 8px 24px -6px rgba(0, 0, 0, 0.6), 0 2px 6px -2px rgba(0, 0, 0, 0.4);
}

/* -----------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

body {
    background-color: var(--surface);
    color: var(--text);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.container { max-width: 1600px; }

/* One focus treatment for the whole app, so keyboard users get a consistent
   and genuinely visible ring instead of per-component guesses. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

.no-select {
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

/* Type -------------------------------------------------------------------- */

.wordmark {
    font-weight: 650;
    letter-spacing: -0.022em;
    color: var(--text);
}

.text-secondary { color: var(--text-secondary); }
.text-muted { color: var(--text-muted); }
.text-accent { color: var(--accent); }

/* Counts and file sizes are measurements, so they get tabular figures. */
.numeric {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

/* -----------------------------------------------------------------------------
   3. Components
   -------------------------------------------------------------------------- */

.panel {
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding-bottom: 0.625rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0.75rem;
}

.panel-title {
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: -0.008em;
    color: var(--text);
}

.section-label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: -0.004em;
    color: var(--text);
}

/* Tabs -------------------------------------------------------------------- */
/* Styling lives here rather than in tabManager.js, which used to add and remove
   hardcoded Tailwind colour classes and so could not follow the theme. */

.tab-strip {
    display: flex;
    gap: 0.125rem;
    border-bottom: 1px solid var(--border);
}

.tab-button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    margin-bottom: -1px;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    cursor: pointer;
    transition: color var(--dur) var(--ease),
                border-color var(--dur) var(--ease),
                background-color var(--dur) var(--ease);
}

.tab-button:hover {
    color: var(--text);
    background-color: var(--surface-sunken);
}

.tab-button.active-tab {
    color: var(--accent);
    border-bottom-color: var(--accent);
    background-color: transparent;
    font-weight: 600;
}

/* Drop zone --------------------------------------------------------------- */

.dropzone {
    display: block;
    padding: 1.5rem 1rem;
    text-align: center;
    background-color: var(--surface-raised);
    border: 1.5px dashed var(--border-strong);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition: border-color var(--dur) var(--ease),
                background-color var(--dur) var(--ease);
}

.dropzone:hover,
.dropzone:focus-within {
    border-color: var(--accent);
    background-color: var(--accent-weak);
}

.dropzone.is-dragover {
    border-style: solid;
    border-color: var(--accent);
    background-color: var(--accent-weak);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.dropzone-icon {
    color: var(--accent);
    font-size: 1.25rem;
}

.dropzone-title {
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: -0.008em;
    color: var(--text);
}

.dropzone-hint {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* Segmented control ------------------------------------------------------- */
/* Three mutually exclusive options. This used to be three cards tinted green,
   orange and red — traffic-light colours implying danger where none exists. */

.segmented {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 3px;
    padding: 3px;
    background-color: var(--control-track);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.segmented-option {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.0625rem;
    padding: 0.4375rem 0.25rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-align: center;
    transition: background-color var(--dur) var(--ease),
                color var(--dur) var(--ease);
}

.segmented-option:hover:not(.is-selected) {
    background-color: color-mix(in srgb, var(--control-selected) 50%, transparent);
}

.segmented-label {
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.25;
    color: var(--text-secondary);
}

.segmented-sub {
    font-size: 0.625rem;
    line-height: 1.25;
    color: var(--text-muted);
}

.segmented-option.is-selected {
    background-color: var(--control-selected);
    box-shadow: var(--shadow-sm);
}

.segmented-option.is-selected .segmented-label {
    color: var(--accent);
    font-weight: 650;
}

.segmented-option.is-selected .segmented-sub { color: var(--text-secondary); }

/* Buttons ----------------------------------------------------------------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4375rem;
    padding: 0.5rem 0.875rem;
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 550;
    line-height: 1.2;
    letter-spacing: -0.006em;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease),
                color var(--dur) var(--ease),
                box-shadow var(--dur) var(--ease);
}

.btn:disabled {
    opacity: 0.42;
    cursor: not-allowed;
    box-shadow: none;
}

.btn-primary {
    background-color: var(--accent-solid);
    color: var(--on-accent);
    box-shadow: var(--shadow-sm);
}

.btn-primary:hover:not(:disabled) {
    background-color: var(--accent-solid-hover);
    box-shadow: var(--shadow-md);
}

.btn-secondary {
    background-color: var(--surface-raised);
    color: var(--text);
    border-color: var(--border-strong);
    box-shadow: var(--shadow-sm);
}

.btn-secondary:hover:not(:disabled) {
    background-color: var(--surface-sunken);
    border-color: var(--text-muted);
}

.btn-quiet {
    background-color: transparent;
    color: var(--text-secondary);
}

.btn-quiet:hover:not(:disabled) {
    background-color: var(--surface-sunken);
    color: var(--text);
}

.btn-sm {
    padding: 0.3125rem 0.625rem;
    font-size: 0.75rem;
}

.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    color: var(--text-secondary);
    background-color: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background-color var(--dur) var(--ease),
                color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
}

.btn-icon:hover {
    background-color: var(--surface-sunken);
    border-color: var(--border);
    color: var(--accent);
}

/* Chips ------------------------------------------------------------------- */

/* `:not(.hidden)` because custom.css loads after tailwind.css — without the
   guard this rule out-ranks `.hidden` on source order and the file count could
   never be hidden. */
.chip:not(.hidden) {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1875rem 0.5rem;
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--text-secondary);
    background-color: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: 999px;
}

.chip-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--accent);
    background-color: var(--accent-weak);
    border-color: var(--accent-border);
}

/* Form controls ----------------------------------------------------------- */

.field {
    padding: 0.25rem 0.5rem;
    font-family: inherit;
    font-size: 0.75rem;
    color: var(--text);
    background-color: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    transition: border-color var(--dur) var(--ease);
}

.field:hover { border-color: var(--accent); }

.checkbox {
    width: 0.875rem;
    height: 0.875rem;
    accent-color: var(--accent);
    cursor: pointer;
}

/* Notices ----------------------------------------------------------------- */
/* Status, success and error share one shape. They differ by border and icon
   colour, not by a bespoke tinted gradient panel each. */

.notice {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5625rem 0.6875rem;
    font-size: 0.75rem;
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
}

.notice-info {
    background-color: var(--accent-weak);
    border-color: var(--accent-border);
}

.notice-info .notice-icon { color: var(--accent); }

.notice-success {
    background-color: var(--success-weak);
    border-color: var(--success-border);
}

.notice-success .notice-icon { color: var(--success); }

.notice-error {
    background-color: var(--danger-weak);
    border-color: var(--danger-border);
}

.notice-error .notice-icon { color: var(--danger); }

.notice-body { flex: 1; min-width: 0; }

/* Progress ---------------------------------------------------------------- */

.progress-track {
    width: 100%;
    height: 4px;
    overflow: hidden;
    background-color: color-mix(in srgb, var(--accent) 18%, transparent);
    border-radius: 999px;
}

/* Width, not scaleX, on purpose. scaleX would squash the rounded end caps, and
   the fill is a 4px bar in its own container so there is no layout cost worth
   optimising away. */
.progress-fill {
    height: 100%;
    background-color: var(--accent);
    border-radius: 999px;
    transition: width 320ms var(--ease);
}

/* File rows --------------------------------------------------------------- */

.file-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0.6875rem;
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    transition: border-color var(--dur) var(--ease),
                background-color var(--dur) var(--ease);
}

.file-row:hover {
    border-color: var(--accent-border);
    background-color: var(--accent-weak);
}

.file-row-name {
    font-size: 0.8125rem;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.file-row-meta {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.6875rem;
    color: var(--text-muted);
}

.file-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.5rem;
    height: 1.5rem;
    color: var(--text-muted);
    background: none;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color var(--dur) var(--ease),
                background-color var(--dur) var(--ease);
}

.file-remove:hover {
    color: var(--danger);
    background-color: var(--danger-weak);
}

/* Empty states ------------------------------------------------------------ */

/* `:not(.hidden)` for the same cascade reason as .chip above. */
.empty-state:not(.hidden) {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.3125rem;
    text-align: center;
    color: var(--text-muted);
}

.empty-state-icon {
    font-size: 1.5rem;
    color: var(--border-strong);
    margin-bottom: 0.25rem;
}

.empty-state-title {
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: -0.008em;
    color: var(--text-secondary);
}

.empty-state-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   4. Layout mechanics — draggable split pane
   -------------------------------------------------------------------------- */

.split-pane-container {
    display: flex;
    position: relative;
    width: 100%;
    height: 100%;
}

.split-pane-left {
    width: 45%;
    min-width: 300px;
    max-width: 70%;
    height: 100%;
    overflow: hidden;
}

.split-pane-splitter {
    position: relative;
    flex-shrink: 0;
    width: 9px;
    cursor: col-resize;
    background-color: transparent;
}

/* The rule is the visible part; the hit area around it stays generous. */
.split-pane-splitter::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1px;
    height: 100%;
    background-color: var(--border);
    /* scaleX rather than animating `width`: this thickens on the compositor
       instead of running layout on every frame of a drag. */
    transform: translate(-50%, -50%) scaleX(1);
    transition: background-color var(--dur) var(--ease),
                transform var(--dur) var(--ease);
}

.split-pane-splitter:hover::before,
.split-pane-splitter.dragging::before {
    transform: translate(-50%, -50%) scaleX(3);
    background-color: var(--accent);
}

.split-pane-right {
    flex: 1;
    height: 100%;
    min-width: 300px;
    overflow-x: hidden;
    overflow-y: auto;
    background-color: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}

#markdown-input {
    font-family: var(--font-mono);
    font-size: 13px;
    line-height: 1.7;
    color: var(--text);
    background-color: var(--surface-raised);
    resize: none;
    tab-size: 4;
}

#markdown-input::placeholder { color: var(--text-muted); }

/* -----------------------------------------------------------------------------
   5. Document preview

   Stays white in both themes on purpose: it previews a printed page, and the
   printed page is white. Tinting it in dark mode would make the preview stop
   matching the PDF the user actually receives.
   -------------------------------------------------------------------------- */

#pdf-preview-container {
    width: 100%;
    max-width: 1000px;
    min-height: 100%;
    padding: 10mm;
    overflow-wrap: break-word;
    background-color: #ffffff;
    color: #24292f;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
}

.preview-content {
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.preview-content table {
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.preview-content table thead tr { background-color: #f6f8fa; }

.preview-content blockquote {
    margin-left: 0;
    padding-left: 1.25em;
    border-left: 3px solid #d1d9e0;
    color: #57606a;
}

.preview-content img {
    display: inline-block;
    max-width: 100%;
    height: auto;
    margin: 2px 4px;
    vertical-align: middle;
    border-radius: var(--radius-sm);
}

/* Shield/badge images wrap naturally instead of forcing a horizontal scroll. */
.preview-content a img[src*="shields.io"],
.preview-content a img[src*="badge"],
.preview-content img[src*="shields.io"],
.preview-content img[src*="badge"] {
    display: inline;
    width: auto;
    max-width: none;
    margin: 3px 4px;
    vertical-align: middle;
}

.preview-content div[align="center"],
.preview-content [style*="text-align: center"],
.preview-content [style*="text-align:center"] {
    text-align: center;
    padding: 8px 0;
    line-height: 1.8;
}

/* -----------------------------------------------------------------------------
   6. Mobile file sheet
   -------------------------------------------------------------------------- */

#mobile-file-fab.show { animation: fab-in 200ms var(--ease) forwards; }
#mobile-file-fab.hide { animation: fab-out 160ms var(--ease) forwards; }

@keyframes fab-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes fab-out {
    from { opacity: 1; transform: translateY(0); }
    to { opacity: 0; transform: translateY(8px); }
}

.fab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5625rem 0.9375rem;
    font-size: 0.8125rem;
    font-weight: 550;
    color: var(--on-accent);
    background-color: var(--accent-solid);
    border: none;
    border-radius: 999px;
    box-shadow: var(--shadow-lg);
    cursor: pointer;
}

.sheet {
    background-color: var(--surface-raised);
    border-top: 1px solid var(--border);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-lg);
}

#mobile-file-modal.show #modal-content {
    animation: sheet-up 220ms var(--ease) forwards;
}

@keyframes sheet-up {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

#mobile-file-modal .modal-backdrop { transition: opacity 200ms var(--ease); }
#mobile-file-modal.hidden .modal-backdrop { opacity: 0; pointer-events: none; }

.mobile-file-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    background-color: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    transition: border-color var(--dur) var(--ease);
}

.mobile-file-item:hover { border-color: var(--accent-border); }

/* -----------------------------------------------------------------------------
   7. Scrollbars
   -------------------------------------------------------------------------- */

.custom-scrollbar,
.split-pane-right {
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
}

.custom-scrollbar::-webkit-scrollbar,
.split-pane-right::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

.custom-scrollbar::-webkit-scrollbar-track,
.split-pane-right::-webkit-scrollbar-track { background: transparent; }

.custom-scrollbar::-webkit-scrollbar-thumb,
.split-pane-right::-webkit-scrollbar-thumb {
    background-color: var(--border-strong);
    border: 3px solid transparent;
    background-clip: content-box;
    border-radius: 999px;
}

.custom-scrollbar::-webkit-scrollbar-thumb:hover,
.split-pane-right::-webkit-scrollbar-thumb:hover {
    background-color: var(--text-muted);
}

/* -----------------------------------------------------------------------------
   8. Responsive & preference queries
   -------------------------------------------------------------------------- */

@media (max-width: 1400px) {
    .container { max-width: 1280px; }
    #pdf-preview-container { max-width: 800px; }
}

@media (max-width: 1200px) {
    #pdf-preview-container { max-width: 700px; }
}

@media (max-width: 768px) {
    .split-pane-container { flex-direction: column; }

    .split-pane-left {
        width: 100% !important;
        max-width: 100% !important;
        height: 50%;
    }

    .split-pane-splitter {
        width: 100%;
        height: 9px;
        cursor: row-resize;
    }

    .split-pane-splitter::before {
        width: 100%;
        height: 1px;
    }

    .split-pane-splitter:hover::before,
    .split-pane-splitter.dragging::before {
        width: 100%;
        height: 3px;
    }

    .split-pane-right {
        height: 50%;
        min-height: 200px;
    }

    #pdf-preview-container {
        max-width: none;
        margin: 0.5rem;
        padding: 6mm;
    }
}

@media (prefers-contrast: more) {
    :root {
        --border: var(--border-strong);
        --text-secondary: var(--text);
    }
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* -----------------------------------------------------------------------------
   Utility precedence note

   The `:not(.hidden)` guards on .chip and .empty-state are the only two
   component rules that set `display` on an element the app also toggles
   `.hidden` on. Writing `.hidden { display: none !important }` here instead is
   tempting and wrong: it also outranks Tailwind's responsive variants, so the
   `hidden lg:flex` wrapper around the file list would never appear on desktop.
   -------------------------------------------------------------------------- */
