/* ============================================================================
 * refresh.css — 2026 modern DARK theme, layered on top of the Beagle theme.
 *
 * Loaded LAST so it wins the cascade. theme.css is a compiled light Bootstrap-4
 * theme, so this re-skins the whole component surface to dark: canvas, header,
 * sidebar, cards, tables, forms, buttons, modals, dropdowns. Layout/positioning
 * is untouched (safe against the structural net); the look is reviewed via the
 * VisualRegressionTest before/after screenshots.
 *
 * Aesthetic: deep slate canvas, slightly-elevated surfaces, hairline borders,
 * a vivid blue accent, soft light type. !important is used throughout to beat
 * the compiled theme's specific selectors.
 * ========================================================================== */

:root {
    --cm-bg: #0e1320;            /* app canvas — deep slate-navy */
    --cm-surface: #171d2c;       /* cards / panels */
    --cm-surface-2: #1e273a;     /* inputs, hover, elevated */
    --cm-header: #121826;        /* top navbar */
    --cm-sidebar: #101622;       /* left sidebar */
    --cm-border: #283246;        /* hairline borders */
    --cm-border-soft: #1f2839;

    --cm-text: #e7ecf6;          /* primary text */
    --cm-text-muted: #95a1ba;    /* secondary text */
    --cm-text-faint: #8893ad;    /* tertiary / placeholders */

    --cm-primary: #4d8bff;
    --cm-primary-rgb: 77, 139, 255;
    --cm-primary-hover: #6a9dff;
    --cm-success: #35c98a;
    --cm-success-rgb: 53, 201, 138;
    --cm-danger: #f25c6e;
    --cm-danger-rgb: 242, 92, 110;
    --cm-warning: #f3b14b;
    --cm-warning-rgb: 243, 177, 75;

    --cm-radius: 12px;
    --cm-radius-sm: 9px;
    --cm-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .28);
}

/* --- Base ----------------------------------------------------------------- */
html, body {
    background-color: var(--cm-bg) !important;
}
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
        Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    color: var(--cm-text) !important;
    letter-spacing: .1px;
}
.be-wrapper, .be-content, .main-content {
    background-color: var(--cm-bg) !important;
}
h1, h2, h3, h4, h5, h6,
.page-head-title, .card-title, .panel-title {
    color: var(--cm-text) !important;
    letter-spacing: -.01em;
}
.text-muted, small, .small, .be-left-sidebar .sidebar-elements li.divider {
    color: var(--cm-text-muted) !important;
}
a {
    color: var(--cm-primary);
}
a:hover {
    color: var(--cm-primary-hover);
}
hr {
    border-color: var(--cm-border) !important;
}

/* Themed scrollbars so the chrome matches the canvas. */
* {
    scrollbar-color: #2c3650 var(--cm-bg);
    scrollbar-width: thin;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: var(--cm-bg); }
*::-webkit-scrollbar-thumb { background: #2c3650; border-radius: 8px; }

/* --- Top header / navbar -------------------------------------------------- */
.be-color-header .be-top-header,
.be-color-header .be-top-header .be-navbar-header,
.be-top-header {
    background-color: var(--cm-header) !important;
    border-bottom: 1px solid var(--cm-border) !important;
}
.be-top-header .be-icons-nav .nav-link,
.be-top-header .be-user-nav .nav-link,
.be-top-header .page-title span {
    color: var(--cm-text) !important;
}
.be-top-header .user-name { color: var(--cm-text) !important; }

/* Hover affordance on the right-side nav icons (info, settings) and the
 * user-dropdown — the theme leaves these flat with just text-decoration:none,
 * so on dark there's no visible cue you can click them. */
.be-top-header .be-icons-nav .nav-link,
.be-top-header .be-user-nav .nav-link {
    transition: background-color .12s ease, color .12s ease;
    border-radius: var(--cm-radius-sm);
}
.be-top-header .be-icons-nav .nav-link:hover,
.be-top-header .be-user-nav .nav-link:hover,
.be-top-header .be-icons-nav .nav-link:focus,
.be-top-header .be-user-nav .nav-link:focus {
    background-color: rgba(var(--cm-primary-rgb), .12);
    color: var(--cm-primary-hover) !important;
}

/* Page title typography. With the in-page .page-head block hidden (rule
 * below), the top-bar title is now the *only* place the page name appears
 * outside the browser tab, so push it back up to a more confident size
 * than the original "subtitle" tone. Theme's 1.46rem + line-height: 60px
 * is still over-the-top against the logo; 1.25rem at weight 600 reads as
 * the document title without competing with the brand. */
.be-top-header .page-title {
    font-size: 1.25rem !important;
    font-weight: 600;
    letter-spacing: .01em;
}
.be-top-header .page-title span {
    opacity: 1;
}

/* Hide the in-page .page-head block (large title + breadcrumb) — duplicates
 * what the top-bar already shows now that #169 made it visible. Frees up
 * ~60-80px of vertical content room on every page. The DOM element stays
 * (we hide via display:none rather than touching every JSP), so tests that
 * read .page-head-title text via textContent still resolve. */
.page-head { display: none; }

/* --- Left sidebar --------------------------------------------------------- *
 * Theme.css ships the sidebar at 230px; we trim to 200px to give the main
 * content area ~30px more horizontal room (and rename "Invoicing and Payments"
 * to the shorter route-matching "Invoices" so nothing wraps at the new width).
 * .be-content's matching gutter has to move in lockstep — both selectors live
 * here, near the rest of the sidebar overrides, so the relationship is local.
 */
/* Geometry only ≥768px: below that, theme.css switches the sidebar to an
 * in-flow full-width collapsible panel and zeroes the content gutter — an
 * unscoped 200px margin/fixed column here is exactly what broke mobile
 * (dead half-screen gutter + sidebar painted over the content). */
@media (min-width: 768px) {
    .be-left-sidebar { width: 200px !important; }
    .be-content      { margin-left: 200px; }
}
.be-login .be-content { margin-left: 0 !important; }  /* see login-fix block below */

/* Force the sidebar to full viewport height so the dark column + right border
 * stay continuous all the way down to the fixed footer at viewport bottom.
 *
 * Theme.css only sets `position: fixed; top: 0; bottom: 0; height: 100%` on
 * the sidebar when the <body> carries the `be-fixed-sidebar` class — and our
 * layouts (main.tag / main_admin.tag) don't set that class, so the default
 * `position: absolute` makes the sidebar collapse to content height. Result:
 * the dark column stopped at the last menu item, leaving an ugly gap between
 * the menu bottom and the build-info footer.
 *
 * Use `top: 61px; bottom: 0` so the sidebar sits below the 61px top header
 * and fills down to the viewport bottom — browser computes height = viewport
 * - 61 - 0. An earlier attempt at this combined top:0 + margin-top:61px +
 * bottom:0 + padding-bottom:61px (mirroring theme literally), but with
 * content-box sizing that pushed the bottom edge 61px past the viewport —
 * caught by detailPage_sidebarDarkColumnExtendsToViewportBottom in CI. */
@media (min-width: 768px) {
    .be-left-sidebar {
        position: fixed !important;
        top: 61px;
        bottom: 0;
        z-index: 1029;
    }
}

.be-left-sidebar,
.be-left-sidebar .left-sidebar-wrapper,
.be-left-sidebar .left-sidebar-content {
    background-color: var(--cm-sidebar) !important;
    border-right: 1px solid var(--cm-border) !important;
}

/* Slim footer pinned to the bottom of the viewport (inside the dark sidebar
 * column), showing the build identity — version / build# / commit / date.
 *
 * Originally tried `position: absolute; bottom: 0`, but the nearest positioned
 * ancestor turned out to be the `display: table` `.left-sidebar-wrapper`,
 * which collapsed to its content height — so the footer rode up the column
 * and overlapped the menu (mid-sidebar, crushing "Users").
 *
 * Use `position: fixed` so it anchors to the viewport, matching the sidebar's
 * own fixed positioning. Width tracks the trimmed sidebar (200px), so it sits
 * flush in the left column. Because it lives INSIDE `.be-left-sidebar` in the
 * DOM, the theme's narrow-viewport `display: none` on the sidebar still hides
 * the footer too. */
.cm-sidebar-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 200px;
    z-index: 1029;          /* same stacking as .be-left-sidebar */
    padding: 10px 16px 12px;
    border-top: 1px solid var(--cm-border);
    font-size: 11px;
    line-height: 1.45;
    color: var(--cm-text-faint);
    background-color: var(--cm-sidebar);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* On mobile the sidebar is an in-flow panel, but this footer is fixed to the
 * viewport — it would float over page content. Build identity is desktop-only. */
@media (max-width: 767.98px) {
    .cm-sidebar-footer { display: none; }
}
.cm-sidebar-footer .cm-bf-version {
    color: var(--cm-text-muted);
    font-weight: 600;
    letter-spacing: .02em;
}
.cm-sidebar-footer .cm-bf-meta {
    display: block;
    opacity: .8;
}
/* Reserve scroll room under the menu so the last items can never end up
 * behind the fixed footer on a short viewport. Theme's .left-sidebar-content
 * uses padding-top: 8px; we just bump padding-bottom. */
.be-left-sidebar .left-sidebar-content { padding-bottom: 64px; }
.be-left-sidebar .sidebar-elements li a {
    color: var(--cm-text-muted) !important;
    border-radius: var(--cm-radius-sm);
    margin: 1px 8px;
    padding-left: 12px;
    transition: background-color .12s ease, color .12s ease;
}
.be-left-sidebar .sidebar-elements li a .icon {
    color: var(--cm-text-faint) !important;
}
.be-left-sidebar .sidebar-elements li a:hover,
.be-left-sidebar .sidebar-elements li a:hover .icon {
    background-color: rgba(var(--cm-primary-rgb), .12);
    color: var(--cm-primary-hover) !important;
}
.be-left-sidebar .sidebar-elements li.active > a,
.be-left-sidebar .sidebar-elements li.active > a .icon {
    background-color: rgba(var(--cm-primary-rgb), .16);
    color: #fff !important;
    font-weight: 600;
}
.be-left-sidebar .sidebar-elements li.divider {
    border-color: var(--cm-border) !important;
    font-weight: 600;
    letter-spacing: .04em;
}

/* --- Surfaces: cards / widgets / panels ----------------------------------- */
.card, .widget, .panel, .main-box,
.modal-content, .dropdown-menu, .login-box, .be-detached-content {
    background-color: var(--cm-surface) !important;
    color: var(--cm-text) !important;
    border: 1px solid var(--cm-border) !important;
    border-radius: var(--cm-radius) !important;
    box-shadow: var(--cm-shadow) !important;
}
.widget { transition: border-color .16s ease, transform .16s ease; }
.widget:hover { border-color: #34415d !important; }
.card-header, .panel-heading, .card-footer, .modal-header, .modal-footer {
    background-color: transparent !important;
    border-color: var(--cm-border) !important;
    color: var(--cm-text) !important;
    font-weight: 600;
}

/* --- Tables --------------------------------------------------------------- */
.table, .table td, .table th {
    color: var(--cm-text) !important;
    border-color: var(--cm-border) !important;
}
.table thead th {
    color: var(--cm-text-muted) !important;
    border-top: 0 !important;
    border-bottom: 1px solid var(--cm-border) !important;
    font-weight: 600;
    text-transform: none;
}
.table td, .table th { padding: .85rem 1rem; vertical-align: middle; }
.table-striped tbody tr:nth-of-type(odd) > * {
    background-color: rgba(255, 255, 255, .02) !important;
}
table.dataTable tbody tr { background-color: transparent !important; transition: background-color .12s ease; }
table.dataTable tbody tr:hover > * {
    background-color: rgba(var(--cm-primary-rgb), .08) !important;
}

/* Flush table cards (.card-table) have a padding:0 body, so a table wider than
   the card — e.g. the job-details Package "Embed Code"/"Media" columns, or a
   wide Encode Details table — used to spill its rows past the card's background
   onto the page canvas. Contain it: clip to the card's rounded corners and let
   an over-wide table scroll horizontally inside the card instead of overrunning
   it. (overflow-x:auto is a no-op when the table already fits.) */
.card-table {
    overflow: hidden;
}
.card-table > .card-body {
    overflow-x: auto;
}

/* DataTables chrome */
.dataTables_wrapper, .dataTables_info, .dataTables_length,
.dataTables_filter, .dataTables_length label, .dataTables_filter label {
    color: var(--cm-text-muted) !important;
}
.dataTables_filter input, .dataTables_length select {
    background-color: var(--cm-surface-2) !important;
    color: var(--cm-text) !important;
    border: 1px solid var(--cm-border) !important;
    border-radius: var(--cm-radius-sm) !important;
    padding: .35rem .6rem;
}
.page-link {
    background-color: var(--cm-surface-2) !important;
    color: var(--cm-text) !important;
    border: 1px solid var(--cm-border) !important;
    border-radius: var(--cm-radius-sm) !important;
    margin: 0 2px;
}
.page-item.active .page-link {
    background-color: var(--cm-primary) !important;
    border-color: var(--cm-primary) !important;
    color: #fff !important;
}
.page-item.disabled .page-link { color: var(--cm-text-faint) !important; opacity: .6; }

/* --- Forms ---------------------------------------------------------------- */
.form-control, .custom-select, textarea, select,
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple,
.select2-dropdown, .select2-search__field {
    background-color: var(--cm-surface-2) !important;
    color: var(--cm-text) !important;
    border: 1px solid var(--cm-border) !important;
    border-radius: var(--cm-radius-sm) !important;
}
.form-control::placeholder, .select2-search__field::placeholder { color: var(--cm-text-faint) !important; }
.form-control:focus, .custom-select:focus, textarea:focus,
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--cm-primary) !important;
    box-shadow: 0 0 0 3px rgba(var(--cm-primary-rgb), .25) !important;
    background-color: var(--cm-surface-2) !important;
}
label, .control-label, .col-form-label { color: var(--cm-text-muted) !important; }
.select2-container--default .select2-results__option[aria-selected=true] { background-color: var(--cm-surface) !important; }
.select2-container--default .select2-results__option--highlighted[aria-selected] { background-color: var(--cm-primary) !important; color: #fff !important; }
.select2-container--default .select2-selection--single .select2-selection__rendered { color: var(--cm-text) !important; }

/* --- Buttons -------------------------------------------------------------- */
.btn {
    border-radius: var(--cm-radius-sm) !important;
    font-weight: 500;
    transition: filter .15s ease, box-shadow .15s ease, transform .05s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary {
    background-color: var(--cm-primary) !important;
    border-color: var(--cm-primary) !important;
    color: #fff !important;
}
.btn-primary:hover, .btn-primary:focus {
    background-color: var(--cm-primary-hover) !important;
    border-color: var(--cm-primary-hover) !important;
    box-shadow: 0 2px 12px rgba(var(--cm-primary-rgb), .4) !important;
}
.btn-default, .btn-secondary, .btn-light {
    background-color: var(--cm-surface-2) !important;
    border-color: var(--cm-border) !important;
    color: var(--cm-text) !important;
}
.btn-default:hover, .btn-secondary:hover, .btn-light:hover { background-color: #283149 !important; }
.btn-link { color: var(--cm-primary) !important; }
.close, .modal-header .close { color: var(--cm-text) !important; text-shadow: none !important; opacity: .8; }

/* --- Dropdown menus (e.g. navbar user menu) ------------------------------- */
.dropdown-menu { border-radius: var(--cm-radius-sm) !important; }
.dropdown-item, .dropdown-menu .user-info .user-name { color: var(--cm-text) !important; }
.dropdown-item:hover, .dropdown-item:focus { background-color: rgba(var(--cm-primary-rgb), .12) !important; color: var(--cm-primary-hover) !important; }
.dropdown-divider { border-color: var(--cm-border) !important; }
.be-top-header .navbar-nav > li.dropdown .dropdown-menu > form > button { color: var(--cm-text) !important; }

/* --- Breadcrumbs / misc --------------------------------------------------- */
.breadcrumb { background-color: transparent !important; }
.breadcrumb-item, .breadcrumb-item.active { color: var(--cm-text-muted) !important; }
.badge-default, .badge-secondary { background-color: var(--cm-surface-2) !important; color: var(--cm-text) !important; }
.modal-backdrop.show { opacity: .6; }

/* --- Brand logo: new SVG wordmark + mark ---------------------------------- *
 * Relative URL so it resolves against the css location (/app/static/css/) ->
 * /app/static/img/. !important beats the per-page inline <style> that points
 * navbar-brand at the old vhost PNG. The login/signup/invite cards use
 * <img class="logo-img">; content: swaps the rendered image without JSP edits. */
.be-color-header .be-top-header .be-navbar-header .navbar-brand,
.be-top-header .be-navbar-header .navbar-brand,
.be-offcanvas-menu .be-left-sidebar .menu-logo {
    background-image: url('../img/logo-cm.svg') !important;
    background-size: contain !important;
    background-position: left center !important;
    background-repeat: no-repeat !important;
    width: 196px !important;
}
.logo-img {
    content: url('../img/logo-cm.svg');
    width: 196px !important;
    height: auto !important;
}

/* --- Login centering fix -------------------------------------------------- *
 * theme.css sets .be-content { margin-left: 230px } to clear the left sidebar,
 * but the login page (nonav layout) has no sidebar, so that gutter pushes the
 * centered .splash-container ~115px to the right. Zero it on login only. */
.be-login .be-content {
    margin-left: 0 !important;
}

/* Numeric data tables (Encode Details / Batch): right-align the numeric columns
   (col 4+ = Bitrate onward; Name/Codec/Resolution stay left) with tabular figures
   so values line up and scan/compare easily. Scoped via the cm-numtable class. */
.cm-numtable td:nth-child(n+4), .cm-numtable th:nth-child(n+4) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Long single-line values (e.g. the full source URL) — clip with an ellipsis and
   expose the full text on hover via title=, instead of widening/scrolling the card. */
.cm-truncate {
    max-width: 340px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ===== P2/P3 UX polish ============================================ */

/* Sidebar: let long labels (e.g. "Invoicing and Payments") wrap instead of
   being truncated with an ellipsis. */
.be-left-sidebar .sidebar-elements li a {
    white-space: normal !important;
    height: auto !important;
    line-height: 1.3;
    padding-top: 9px;
    padding-bottom: 9px;
}

/* Simple forms (submit job/batch, kill batch, password change): cap control
   width so fields don't stretch the full card and are easier to scan. */
.form-signin .form-control,
.form-signin .custom-select,
.form-signin select,
.form-signin textarea {
    max-width: 560px;
}

/* Request JSON: cap height and scroll instead of letting a big profile dominate. */
#jsonOutput {
    max-height: 360px;
    overflow: auto;
}

/* Glanceable quality tints for encode-details numeric cells (classes added by
 * colorEncodeMetrics() in refresh.js). Three buckets covering all the columns
 * the encode-details tables surface — VMAF, min VMAF, VMAF SD, Num Retry,
 * "% Below NN", "% above NN". Thresholds and per-column direction live in
 * refresh.js; here we just paint them. Supersedes the original VMAF-only
 * `.cm-vmaf-low/good` classes from #157. */
.cm-numtable td.cm-metric-good { color: var(--cm-success) !important; }
.cm-numtable td.cm-metric-warn { color: var(--cm-warning) !important; }
.cm-numtable td.cm-metric-bad  { color: var(--cm-danger)  !important; font-weight: 600; }

/* Sticky table headers (#167) were reverted: they pinned correctly, but the
 * standard sticky-thead trade-off — the first tbody row's top scrolls *behind*
 * the pinned header as the page scrolls past it — was reported as confusing
 * UX ("the first variant has its top few lines covered by the titles").
 * Plain non-sticky thead from here. Users on long tables can scroll back up
 * to re-read the column labels; the cost of that is lower than the cost of
 * partial-row occlusion. If we want it back later, the right approach is
 * probably scroll-snapping the table or freezing the first row, not a simple
 * `position: sticky` on the th cells. */

/* --- Pipeline stepper (job-details in-progress) --------------------------- *
 * Visual companion to the phase-aware Status text from #160. The four
 * pipeline stages (Download? · Split · Encode · Package) render as a
 * CONNECTED stepper — this is the product's signature flow, so it should
 * read as one process, not four disconnected button-look pills (pre-launch
 * review, section C1). Markup contract unchanged: <ol class=cm-phase-strip>
 * with per-<li> state classes from the JSP. Each li = icon-in-circle +
 * label; `li + li::before` draws the connector, which inherits green from
 * the *preceding* completed step via the sibling selector. The active
 * step's circle pulses softly — the page's one deliberate motion accent. */
.cm-phase-strip {
    list-style: none;
    margin: 0 0 1.1rem 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    row-gap: 6px;
    align-items: center;
    font-size: 12.5px;
}
.cm-phase-strip li {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--cm-text-faint);     /* pending */
    line-height: 1.2;
    font-weight: 600;
    letter-spacing: .02em;
    white-space: nowrap;
}
/* Connector line between steps; colored by the state of the step BEFORE it. */
.cm-phase-strip li + li::before {
    content: "";
    width: 34px;
    height: 2px;
    margin: 0 10px;
    border-radius: 1px;
    background: var(--cm-border);
}
.cm-phase-strip li.cm-phase-complete + li::before {
    background: rgba(var(--cm-success-rgb), .55);
}
.cm-phase-strip li.cm-phase-errored + li::before {
    background: rgba(var(--cm-danger-rgb), .45);
}
/* The phase icon becomes a state-colored circle. */
.cm-phase-strip li i.mdi {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    font-size: 14px;
    line-height: 1;
    color: var(--cm-text-faint);
    background: var(--cm-surface);
    border: 1px solid var(--cm-border);
}
.cm-phase-strip li.cm-phase-complete { color: var(--cm-success); }
.cm-phase-strip li.cm-phase-complete i.mdi {
    color: #fff;
    background: rgba(var(--cm-success-rgb), .85);
    border-color: transparent;
}
.cm-phase-strip li.cm-phase-active { color: var(--cm-text); }
.cm-phase-strip li.cm-phase-active i.mdi {
    color: #fff;
    background: var(--cm-primary);
    border-color: transparent;
    animation: cm-phase-pulse 2.2s ease-out infinite;
}
.cm-phase-strip li.cm-phase-errored { color: var(--cm-danger); }
.cm-phase-strip li.cm-phase-errored i.mdi {
    color: #fff;
    background: rgba(var(--cm-danger-rgb), .9);
    border-color: transparent;
}
@keyframes cm-phase-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--cm-primary-rgb), .45); }
    70%  { box-shadow: 0 0 0 9px rgba(var(--cm-primary-rgb), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--cm-primary-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
    .cm-phase-strip li.cm-phase-active i.mdi { animation: none; }
}

/* --- Middle-ellipsis URL truncation -------------------------------------- *
 * Companion to refresh.js's truncateUrls(). The JS injects two spans inside
 * each <a class="cm-url-truncate">: .cm-url-short (scheme://host/.../filename)
 * and .cm-url-full (the original URL, hidden). Hover swaps them, with a
 * dotted underline as the affordance that there's more there. */
a.cm-url-truncate {
    /* Allow the long full-URL form to wrap on hover without overflowing. */
    word-break: break-all;
    text-decoration-line: underline;
    text-decoration-style: dotted;
    text-underline-offset: 2px;
}
a.cm-url-truncate .cm-url-full  { display: none; }
a.cm-url-truncate:hover .cm-url-short { display: none; }
a.cm-url-truncate:hover .cm-url-full  { display: inline; }
/* On hover, drop the dotted-underline cue — the user already has the
   information they were looking for. */
a.cm-url-truncate:hover { text-decoration-style: solid; }

/* ===== Appearance polish (pre-launch review, section C) ================== */

/* --- Typography ----------------------------------------------------------- *
 * Two vendored faces (static/fonts/, woff2 latin subsets, no runtime CDN):
 *   Sora          — display face: card/page headings and large stat numerals.
 *                   Variable file covers 400–700.
 *   IBM Plex Mono — machine identifiers: ULIDs, JSON, queue names, API keys.
 * Body copy intentionally stays on the existing system stack — re-metricing
 * all 81 views is full-modernization territory, not this overlay. */
@font-face {
    font-family: "Sora";
    src: url("../fonts/sora-var.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "IBM Plex Mono";
    src: url("../fonts/plexmono-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "IBM Plex Mono";
    src: url("../fonts/plexmono-600.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
:root {
    --cm-font-display: "Sora", -apple-system, BlinkMacSystemFont, "Segoe UI",
        Roboto, Helvetica, Arial, sans-serif;
    --cm-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo,
        Consolas, monospace;
}
h1, h2, h3, h4, h5, h6,
.card-header, .card-title, .panel-title,
.be-top-header .page-title,
.modal-title {
    font-family: var(--cm-font-display);
}
.card-header { font-weight: 600; font-size: 1.02rem; }
/* Machine identifiers & code-like values. cm-id is added by the JSPs around
 * job identifiers; JSON boxes and truncated URLs opt in by existing class. */
.cm-id, #jsonOutput, pre, code, kbd,
a.cm-url-truncate, .cm-url-short, .cm-url-full {
    font-family: var(--cm-font-mono);
    font-size: .925em;
}
.cm-id { letter-spacing: .01em; }
/* Tabular figures wherever numbers stack vertically. */
.cm-numtable td, .widget-tile h1, .dataTables_info {
    font-variant-numeric: tabular-nums;
}

/* --- Dashboard stat tiles -------------------------------------------------- *
 * The big numerals move to the display face; the leftover Bootstrap-3
 * glyphicon <i> elements render as empty boxes in BS4 — hide them rather
 * than chase the dead font. cm-stat-warn (set by the JSP when blocked > 0)
 * tints the one number that deserves attention. */
.widget-tile h1 {
    font-family: var(--cm-font-display);
    font-weight: 700;
    font-size: 2.35rem;
    letter-spacing: -.02em;
}
.widget-tile h1 .glyphicon { display: none; }
.widget-tile h1.cm-stat-warn { color: var(--cm-warning); }
.widget-tile h6 {
    color: var(--cm-text-muted) !important;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    font-size: .68rem;
}

/* --- Encode progress bar --------------------------------------------------- *
 * The stacked bar's segments: encoded=bg-success, errored=bg-danger,
 * encoding=bg-primary, remaining=bg-grey. On the dark theme the grey
 * "remaining" segment rendered BRIGHT with animated stripes — visually
 * indistinguishable from active fill, so a 3%-done job read as 97%-done
 * (pre-launch review, B1). Remaining goes quiet: dark, label faint, no
 * stripes/animation. Classes stay untouched — `progress-bar-striped` is
 * the data-refresh poll keepalive marker, so we neutralize its *paint*
 * on the remaining segment only, never the class itself. */
.progress {
    height: 22px !important;
    background-color: var(--cm-bg) !important;
    border: 1px solid var(--cm-border);
    border-radius: 999px !important;
    overflow: hidden;
}
.progress-bar {
    font-size: 11.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 1px rgba(0, 0, 0, .35);
}
.progress-bar.bg-grey {
    background-color: transparent !important;
    background-image: none !important;
    animation: none !important;
    color: var(--cm-text-faint);
    text-shadow: none;
}
/* Stripes/animation are painted on the ACTIVE (encoding) segment only —
 * completed work is solid, matching the stepper's solid-green=done /
 * blue+motion=active semantics. The striped/animated CLASSES stay on every
 * segment (poll keepalive marker); only the paint is scoped. */
.progress-bar.bg-success, .progress-bar.bg-danger {
    background-image: none !important;
    animation: none !important;
}
.progress-bar.bg-success { background-color: var(--cm-success) !important; }
.progress-bar.bg-danger  { background-color: var(--cm-danger) !important; }
.progress-bar.bg-primary { background-color: var(--cm-primary) !important; }
/* Color key under the bar; cm-legend's card-header padding doesn't apply here. */
.cm-progress-legend { padding: 0; margin-top: -10px; }
.cm-legend .cm-dot-active { background: var(--cm-primary); }

/* --- Quality metric chips -------------------------------------------------- *
 * colorEncodeMetrics() (refresh.js) classifies numeric cells and now also
 * wraps the value in span.cm-metric-chip; these rules turn the bare colored
 * text into a small tinted pill so the eye can scan a column of verdicts.
 * The td-level color rules above are kept as a fallback for any cell the
 * wrap skips. */
.cm-metric-chip {
    display: inline-block;
    padding: 1px 9px;
    border-radius: 999px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
td.cm-metric-good .cm-metric-chip {
    background: rgba(var(--cm-success-rgb), .14);
    color: var(--cm-success);
}
td.cm-metric-warn .cm-metric-chip {
    background: rgba(var(--cm-warning-rgb), .14);
    color: var(--cm-warning);
}
td.cm-metric-bad .cm-metric-chip {
    background: rgba(var(--cm-danger-rgb), .16);
    color: var(--cm-danger);
}
/* Legend line under the Encode Details header (added by the JSP). */
.cm-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    align-items: center;
    padding: 8px 1.25rem 2px;
    font-size: 11.5px;
    color: var(--cm-text-faint);
}
.cm-legend .cm-legend-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 5px;
    vertical-align: 1px;
}
.cm-legend .cm-dot-good { background: var(--cm-success); }
.cm-legend .cm-dot-warn { background: var(--cm-warning); }
.cm-legend .cm-dot-bad  { background: var(--cm-danger); }

/* --- Collapse toggles read as expanders, not disabled buttons -------------- *
 * "Request JSON" / "Source Media Info" headers looked grey-on-grey inert
 * (review C4). Make the whole header row an obvious affordance and rotate
 * the chevron when open. */
.card-header button[data-toggle="collapse"] {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 0;
    text-align: left;
    color: var(--cm-text) !important;
    font-family: var(--cm-font-display);
    font-weight: 600;
    font-size: 1.02rem;
    background: transparent;
    border: 0;
    box-shadow: none !important;
}
.card-header button[data-toggle="collapse"]:hover { color: var(--cm-primary-hover) !important; }
.card-header button[data-toggle="collapse"] .mdi-chevron-right {
    color: var(--cm-primary);
    font-size: 18px;
    transition: transform .15s ease;
}
.card-header button[data-toggle="collapse"][aria-expanded="true"] .mdi-chevron-right {
    transform: rotate(90deg);
}

/* --- Completed-job preview actions ----------------------------------------- *
 * Replaces the "Click here for X preview" link pile with one labeled
 * button row (JSP provides .cm-preview-actions). */
.cm-preview-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    padding: 14px 1.25rem;
}
.cm-preview-actions .cm-preview-label {
    color: var(--cm-text-muted);
    font-weight: 600;
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    margin-right: 2px;
}
.cm-preview-actions .btn { padding: .3rem .8rem; font-size: .85rem; }

/* --- Density: stop narrow forms floating in a void -------------------------- *
 * Single-card form pages (submit job/batch, password change…) cap and keep
 * a balanced measure; :has() is fine for our Chromium/Firefox audience. */
.main-content .card:has(form.form-signin) {
    max-width: 880px;
}
/* Content column itself gets a sane ceiling on very wide screens. */
@media (min-width: 1500px) {
    .main-content.container-fluid { max-width: 1440px; margin-inline: auto; }
}

/* --- Custom checkboxes (login "Remember Me" et al) -------------------------- */
.custom-control-label::before {
    background-color: var(--cm-surface-2) !important;
    border: 1px solid var(--cm-border) !important;
}
.custom-control-input:checked ~ .custom-control-label::before {
    background-color: var(--cm-primary) !important;
    border-color: var(--cm-primary) !important;
}
.custom-control-input:focus ~ .custom-control-label::before {
    box-shadow: 0 0 0 3px rgba(var(--cm-primary-rgb), .25) !important;
}

/* --- Mobile (≤767.98px): extend the dark theme to the phone layout ---------- *
 * theme.css swaps to: fixed full-width BLUE .be-right-navbar bar, white
 * .left-sidebar-toggle strip ("Page ▾"), sidebar as in-flow light panel.
 * None of those were covered by the overlay (review A6). */
@media (max-width: 767.98px) {
    .be-top-header .be-right-navbar {
        background-color: var(--cm-header) !important;
        border-bottom: 1px solid var(--cm-border) !important;
    }
    .be-top-header .be-right-navbar .navbar-nav > li > a.nav-link,
    .be-top-header .be-right-navbar .user-name { color: var(--cm-text) !important; }
    /* The page-title strip that toggles the collapsed nav. */
    .be-left-sidebar .left-sidebar-toggle,
    .be-top-header .be-toggle-top-header-menu {
        background-color: var(--cm-surface) !important;
        color: var(--cm-text) !important;
        border-bottom: 1px solid var(--cm-border) !important;
    }
    /* Sidebar becomes an in-flow panel: keep it dark, drop desktop chrome.
     * height:auto kills the inherited 100%-height that otherwise reserves a
     * full empty viewport between the toggle strip and the page content. */
    .be-left-sidebar,
    .be-left-sidebar .left-sidebar-wrapper {
        height: auto !important;
        min-height: 0 !important;
    }
    .be-left-sidebar {
        background-color: var(--cm-sidebar) !important;
        border-bottom: 1px solid var(--cm-border) !important;
        border-right: 0 !important;
    }
    /* Breathing room: the canvas gutter is gone, let cards use the width. */
    .main-content.container-fluid { padding: 12px 10px; }
    .cm-phase-strip li + li::before { width: 16px; margin: 0 6px; }
}

/* --- Per-segment status list (job-details Encode Progress card) ------------ */
.cm-seg-scroll {
    max-height: 320px;
    overflow-y: auto;
    border-top: 1px solid var(--cm-border-soft);
    margin-top: 14px;
}
.cm-seg-table { margin: 0; }
.cm-seg-table td, .cm-seg-table th {
    padding: .45rem 1rem;
    font-size: 13px;
}
.cm-seg-table td:first-child {
    font-family: var(--cm-font-mono);
    color: var(--cm-text-muted);
}
.cm-seg-empty {
    padding: 12px 2px;
    color: var(--cm-text-faint);
    font-size: 13px;
}
/* Status chips share the metric-chip look with state-specific tints. */
.cm-chip {
    display: inline-block;
    padding: 1px 9px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 11.5px;
}
.cm-chip-done   { background: rgba(var(--cm-success-rgb), .14); color: var(--cm-success); }
.cm-chip-active { background: rgba(var(--cm-primary-rgb), .16); color: var(--cm-primary-hover); }
.cm-chip-fail   { background: rgba(var(--cm-danger-rgb), .16);  color: var(--cm-danger); }
.cm-chip-pend   { background: var(--cm-surface-2); color: var(--cm-text-faint); }

/* --- Login: request-access line under the submit button -------------------- */
.cm-login-signup {
    text-align: center;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--cm-border-soft);
    color: var(--cm-text-muted);
    font-size: 13px;
}

/* --- Stripe card element (payment-methods modal) ---------------------------- */
.cm-card-element { padding-top: .55rem; min-height: 42px; }
.cm-card-errors { color: var(--cm-danger); font-size: 12.5px; margin-top: 6px; min-height: 16px; }
