/* Styles shared by every page under /estimates.
   These live in a plain stylesheet rather than scoped component CSS because six components
   share them. Colors come from the --vml-* tokens defined in app.css. */

.est-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.25rem;
}

    .est-header h1 {
        color: var(--vml-black);
        margin: 0;
    }

.est-header-links {
    display: flex;
    align-items: center;
    gap: 1rem;
    font-size: 0.9rem;
}

.est-crumb {
    font-size: 0.85rem;
    color: var(--vml-gray-dark);
    margin: 0 0 0.15rem;
}

.est-page h2 {
    color: var(--vml-black);
    font-size: 1.2rem;
    margin-top: 2rem;
}

.est-page h3 {
    color: var(--vml-black);
    font-size: 1rem;
    margin-top: 1.25rem;
}

/* ------------------------------------------------------------------- tables */

.est-table {
    width: 100%;
    border-collapse: collapse;
    background-color: var(--vml-white);
    margin-bottom: 1.5rem;
}

    .est-table th, .est-table td {
        text-align: left;
        padding: 0.5rem 0.75rem;
        border-bottom: 1px solid var(--vml-gray-light);
        font-size: 0.9rem;
        vertical-align: middle;
    }

    .est-table th {
        color: var(--vml-gray-dark);
        font-weight: 600;
        border-bottom: 2px solid var(--vml-gray-light);
    }

    .est-table td.num, .est-table th.num {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    .est-table td.strong {
        font-weight: 600;
    }

    .est-table input.form-control, .est-table select.form-control {
        width: 100%;
        min-width: 8rem;
        padding: 0.25rem 0.45rem;
        border: 1px solid #ccc;
        border-radius: 4px;
        font-size: 0.85rem;
    }

.est-row-hidden {
    opacity: 0.55;
}

.est-sku {
    display: block;
    font-size: 0.78rem;
    color: var(--vml-gray-dark);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.est-empty {
    background-color: var(--vml-white);
    border: 1px dashed #d4d4d4;
    border-radius: 6px;
    padding: 1.25rem 1.5rem;
    color: var(--vml-gray-dark);
    margin-bottom: 1.5rem;
}

    .est-empty p {
        margin: 0;
    }

/* ------------------------------------------------------------ definition lists */

.est-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 2rem;
    margin: 0.75rem 0 1.5rem;
}

    .est-meta div {
        min-width: 8rem;
    }

    .est-meta dt {
        font-size: 0.75rem;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        color: var(--vml-gray-dark);
        font-weight: 600;
    }

    .est-meta dd {
        margin: 0;
        font-size: 0.9rem;
    }

/* ------------------------------------------------------------------- layout */

.est-columns {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
}

@media (max-width: 900px) {
    .est-columns {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The estimate form itself: two columns of inputs with a vertical rule between them, the way
   the WordPress Create Estimate screen has always looked, so estimators are not relearning the
   page. Everything full width (the versions grid, the buttons, the plan results) sits below. */
.est-form-columns {
    display: grid;
    /* Not an even split: the left column holds short fields — a title, a quantity, an inch
       measurement — and at half of a wide screen it sat half empty. 34rem is enough for its widest
       row (quantity, width and height side by side) and hands the rest to the right column, whose
       device list and notes actually use it. */
    grid-template-columns: minmax(0, 34rem) minmax(0, 1fr);
    gap: 0 2rem;
    align-items: start;
    /* Bounded, or on a 2560px monitor the right column runs to 1670px and its headings and hint
       paragraphs become an unreadable measure. Wide enough to keep the imposition selects on one
       row; past it the slack is left on the right, as with the versions grid. */
    max-width: 88rem;
}

    .est-form-columns > .est-col + .est-col {
        border-left: 1px solid var(--vml-gray-light);
        padding-left: 2rem;
    }

@media (max-width: 1000px) {
    .est-form-columns {
        grid-template-columns: minmax(0, 1fr);
    }

        /* Stacked, the rule would sit above a column rather than beside it. */
        .est-form-columns > .est-col + .est-col {
            border-left: none;
            padding-left: 0;
            border-top: 1px solid var(--vml-gray-light);
            padding-top: 1rem;
            margin-top: 1rem;
        }
}

.est-full {
    margin-top: 1.25rem;
    /* Shares the measure the two columns use, so the buttons, the versions grid and the plan
       results all line up with the form above them instead of running past its right edge. */
    max-width: 88rem;
}

/* Plan results, now beneath the form rather than beside it. */
.est-results-below {
    max-width: 88rem;
    margin-top: 1.5rem;
    border-top: 1px solid var(--vml-gray-light);
    padding-top: 1rem;
}

/* A checkbox and its label on one line. The label is the click target, so it carries the cursor
   and the spacing; a bare grid row would put the box on a line of its own. */
.est-toggle {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0.35rem 0;
    cursor: pointer;
    font-size: 0.9rem;
}

    .est-toggle input[type="checkbox"] {
        /* Bootstrap stretches a bare checkbox inside a flex row. */
        flex: 0 0 auto;
        margin: 0;
    }

/* Fields that only exist because the switch above them is on, indented to show they belong to it. */
.est-indent {
    margin-left: 1.5rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--vml-gray-light);
}

/* Versions grid. Wide by nature — up to eight columns — so it gets its own horizontal scroll
   rather than forcing the page to scroll sideways. */
.est-versions-head {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.est-versions-scroll {
    overflow-x: auto;
    max-width: 100%;
}

.est-versions {
    border-collapse: collapse;
    width: 100%;
    /* Stops the grid spanning a wide monitor. Past this width the fields gain nothing from being
       larger — a quantity is three digits however much room it is given — so the slack is left as
       space on the right instead. Below it the table still fills the page on a laptop. */
    max-width: 74rem;
    /* Fixed layout so the widths below are honoured instead of being renegotiated from content;
       without it a long description or a wide <select> option pushes the other columns around. */
    table-layout: fixed;
    font-size: 0.85rem;
}

    .est-versions th, .est-versions td {
        padding: 0.25rem 0.4rem;
        text-align: left;
        white-space: nowrap;
        vertical-align: middle;
    }

    .est-versions thead th {
        border-bottom: 1px solid var(--vml-gray-light);
        font-weight: 600;
        color: var(--vml-gray-dark);
    }

    /* Fill the cell exactly. min-width on an input beats a table column's width and was what
       made every column stretch. */
    .est-versions td .form-control {
        width: 100%;
        min-width: 0;
    }

/* Sized to their content: only Description is open-ended, so it absorbs whatever is left over. */
.est-versions .est-v-no {
    width: 4rem;
    text-align: center;
    color: var(--vml-gray-dark);
    font-variant-numeric: tabular-nums;
}

.est-versions .est-v-sku {
    /* Around 30 characters, the practical maximum, though most are shorter. */
    width: 15rem;
}

.est-versions .est-v-desc {
    width: auto;
}

.est-versions .est-v-size {
    width: 7rem;
}

.est-versions .est-v-spot {
    width: 11rem;
}

.est-versions .est-v-qty {
    /* Three digits plus the number spinner, and no more. */
    width: 6rem;
}

.est-versions .est-v-actions {
    width: 5.5rem;
}

    .est-versions .est-v-qty .form-control,
    .est-versions .est-v-size .form-control {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

/* Narrow enough that fixed columns no longer fit; the container scrolls rather than crushing them. */
@media (max-width: 800px) {
    .est-versions {
        table-layout: auto;
        min-width: 46rem;
    }
}

/* Numeric inputs are short by nature — a quantity, a bleed, an inch measurement — and the form
   grid would otherwise stretch each one to fill its whole column. A cap rather than a fixed width,
   so they still shrink with the grid on a narrow screen. Scoped to the two input columns: the
   versions grid below sets its own column widths and its inputs must keep filling their cells. */
.est-col input[type="number"] {
    max-width: 8rem;
}

/* One laminating or mounting pass. The rule and indent group a pass's fields together — the
   cascade can run five deep, and without it the second pass reads as more of the first. */
.est-lam-slot {
    padding-left: 0.75rem;
    border-left: 2px solid var(--vml-gray-light);
    margin-bottom: 0.75rem;
}

    .est-lam-slot h3 {
        font-size: 0.85rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--vml-gray-dark);
        margin: 0.25rem 0 0.5rem;
    }

.est-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0 1rem;
}

/* ---------------------------------------------------------------- estimate form rhythm
   The shared .est-form-grid above stretches its columns to 1fr, which is right on the Cosmetics
   pages but wrong here: with the fields themselves sized, a stretched column just parks a
   quantity and a width at opposite ends of the row. These rules are scoped to .est-col so the
   other pages using .est-form-grid are untouched.

   The form is long — around forty controls per column — so the grouping does the work: fields
   sized to their content and packed left, tight spacing within a group, and a headed rule
   between groups. Proximity is what tells an estimator which fields belong together. */
.est-col .est-form-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0 1.25rem;
}

    /* Sized to the field rather than to a share of the row, between bounds: a fixed width either
       clipped a long select ("Any direction (Phoenix may rotate)", material names) or wrapped a
       long label. auto lets each row take what its content needs inside those limits. */
    .est-col .est-form-grid > .form-row {
        flex: 0 1 auto;
        width: auto;
        min-width: 11rem;
        max-width: 22rem;
    }

    /* A quantity, a bleed, an inch measurement needs no more than 8rem of box — but the row still
       grows to fit its label, so "Design time (minutes)" stays on one line. The input itself is
       held at 8rem by the numeric cap above. */
    .est-col .est-form-grid > .form-row-num {
        width: auto;
        min-width: 8rem;
        max-width: 12rem;
    }

.est-col .form-row {
    margin-bottom: 0.6rem;
}


/* Consecutive switches read as one list instead of a scatter of separate rows. */
.est-col .est-toggle {
    margin: 0.2rem 0;
}

/* Section headings become group separators. Quieter and smaller than a page heading, matching the
   uppercase field labels used on the estimate detail page. */
.est-col h2, .est-full h2 {
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--vml-gray-dark);
    margin: 1.6rem 0 0.7rem;
    padding-bottom: 0.3rem;
    border-bottom: 1px solid var(--vml-gray-light);
}

    /* No leading gap above the first group in a column. */
    .est-col > h2:first-child, .est-full > h2:first-child {
        margin-top: 0;
    }

.est-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0 1.25rem;
    margin-bottom: 0.5rem;
}

    .est-filters .form-row {
        max-width: 14rem;
        margin-bottom: 0.6rem;
    }

/* Reused from the Users page conventions so the estimating forms match the rest of the portal. */
.est-page .form-row {
    max-width: 380px;
    margin-bottom: 0.9rem;
}

    .est-page .form-row label {
        display: block;
        font-size: 0.85rem;
        color: var(--vml-gray-dark);
        margin-bottom: 0.25rem;
    }

    .est-page .form-row .form-control {
        width: 100%;
        padding: 0.45rem 0.7rem;
        border: 1px solid #ccc;
        border-radius: 4px;
        font-size: 0.95rem;
    }

        /* Placeholders are hints, not content. The browser default is dark enough that a sample
           value in an empty required field reads as though someone already typed it. */
        .est-page .form-control::placeholder {
            color: #a6a6a6;
            opacity: 1; /* Firefox dims placeholders again on top of the color. */
        }

    .est-page .form-row.form-check {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        /* Bootstrap's own .form-check sets padding-left: 1.5em to make room for a checkbox it
           pulls back with a negative margin. This layout puts the checkbox in the flex flow
           instead, so that padding is left over as a 24px indent — enough to visibly push the row
           out of line with every other field in its section. */
        padding-left: 0;
    }

        .est-page .form-row.form-check input {
            width: 1em;
            height: 1em;
            flex-shrink: 0;
            margin: 0;
        }

        .est-page .form-row.form-check label {
            margin: 0;
        }

.form-row-wide {
    max-width: 100%;
}

/* -------------------------------------------------------------------- text */

.est-hint {
    font-size: 0.82rem;
    color: var(--vml-gray-dark);
    margin: 0.2rem 0 0.6rem;
}

.est-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8rem;
    word-break: break-word;
}

pre.est-mono {
    background-color: #fbfbfb;
    border: 1px solid var(--vml-gray-light);
    border-radius: 4px;
    padding: 0.75rem;
    max-height: 26rem;
    overflow: auto;
}

/* ------------------------------------------------------------------ devices */

.est-devices {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin-bottom: 1rem;
}

.est-device {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    font-size: 0.9rem;
}

.est-device-type {
    font-size: 0.78rem;
    color: var(--vml-gray-dark);
}

.est-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 1.5rem 0;
}

    .est-actions .est-hint {
        flex: 1 1 14rem;
        margin: 0;
    }

/* ------------------------------------------------------------ result panels */

.est-panel {
    background-color: var(--vml-white);
    border: 1px solid var(--vml-gray-light);
    border-top: 3px solid var(--vml-blue);
    border-radius: 6px;
    padding: 1rem 1.25rem 1.25rem;
}

    .est-panel h2 {
        margin-top: 0;
    }

.est-panel-quiet {
    border-top-color: var(--vml-gray-light);
}

.est-plan {
    border: 1px solid var(--vml-gray-light);
    border-radius: 5px;
    padding: 0.75rem 0.9rem;
    margin-bottom: 0.9rem;
}

.est-plan-best {
    border-color: var(--vml-blue);
    background-color: rgba(0, 142, 194, 0.04);
}

.est-plan-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
}

.est-plan-rank {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: var(--vml-gray-dark);
}

.est-plan-total {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--vml-black);
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

.est-plan-each {
    font-size: 0.85rem;
    color: var(--vml-gray-dark);
    font-variant-numeric: tabular-nums;
}

.est-cost {
    border-collapse: collapse;
    margin-bottom: 0.5rem;
}

    .est-cost th, .est-cost td {
        padding: 0.2rem 0.9rem 0.2rem 0;
        font-size: 0.88rem;
    }

    .est-cost th {
        text-align: left;
        font-weight: 400;
        color: var(--vml-gray-dark);
        min-width: 6rem;
    }

    .est-cost td.num {
        text-align: right;
        font-variant-numeric: tabular-nums;
        min-width: 6rem;
    }

/* The cost column is right-aligned, so an inline badge sits between the number and the column
   edge and pushes the number left — that one row then no longer lines up with the rest. Reserve a
   fixed gutter on every value cell and hang the badge in it, so the figures stay in a column and
   the badge sits outside them. */
.est-cost td.num {
    position: relative;
    padding-right: 3rem;
}

.est-cost .badge-est, .est-cost .est-warn {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    margin-left: 0;
}

.est-cost-large th, .est-cost-large td {
    font-size: 1rem;
    padding: 0.35rem 1.25rem 0.35rem 0;
}

.est-cost-total th, .est-cost-total td {
    border-top: 2px solid var(--vml-gray-light);
    font-weight: 700;
    color: var(--vml-black);
    padding-top: 0.5rem;
}

.est-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 1.1rem;
    font-size: 0.85rem;
    color: var(--vml-gray-dark);
}

.est-thumb {
    max-width: 100%;
    border: 1px solid var(--vml-gray-light);
    border-radius: 4px;
    margin-top: 0.6rem;
}

/* A small badge for values that need a caveat — e.g. a $0 cutting cost, which usually means
   Phoenix found no cut path rather than that cutting is free. */
.est-warn {
    display: inline-block;
    width: 1.05em;
    height: 1.05em;
    line-height: 1.05em;
    text-align: center;
    border-radius: 50%;
    background-color: #f0ad4e;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    cursor: help;
    margin-left: 0.3rem;
}

.est-warn-text {
    color: #b8761a;
}

/* --------------------------------------------------------------- stat tiles */

.est-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 1rem 0 1.5rem;
}

.est-tile {
    background-color: var(--vml-white);
    border: 1px solid var(--vml-gray-light);
    border-top: 3px solid var(--vml-blue);
    border-radius: 6px;
    padding: 0.75rem 1.1rem;
    min-width: 7.5rem;
    display: flex;
    flex-direction: column;
}

.est-tile-warn {
    border-top-color: #f0ad4e;
}

.est-tile-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--vml-black);
    font-variant-numeric: tabular-nums;
}

.est-tile-label {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--vml-gray-dark);
}

/* ---------------------------------------------------------------- audit runs */

.est-run {
    background-color: var(--vml-white);
    border: 1px solid var(--vml-gray-light);
    border-radius: 5px;
    padding: 0.6rem 0.9rem;
    margin-bottom: 0.5rem;
}

    .est-run summary {
        cursor: pointer;
        font-size: 0.88rem;
        display: flex;
        align-items: center;
        gap: 0.55rem;
        flex-wrap: wrap;
    }

        .est-run summary .est-hint {
            margin: 0;
        }

/* ------------------------------------------ shared status/badge/action styles
   The Users page has equivalents in its scoped CSS; the estimating pages need them
   unscoped because several components share them. */

.status-message {
    background-color: #eaf6ec;
    border: 1px solid #b9e0bf;
    color: #2f6d3a;
    border-radius: 4px;
    padding: 0.6rem 0.9rem;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.error-message {
    background-color: #fdecea;
    border: 1px solid #f5c6c1;
    color: #c0392b;
    border-radius: 4px;
    padding: 0.6rem 0.9rem;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.est-page .badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 3px;
    font-size: 0.75rem;
    font-weight: 600;
    vertical-align: middle;
}

.est-page .badge-on {
    background-color: rgba(0, 142, 194, 0.12);
    color: var(--vml-blue);
}

.est-page .badge-off {
    background-color: var(--vml-gray-light);
    color: var(--vml-gray-dark);
}

/* A value that was modelled here rather than returned by Phoenix. Amber rather than grey —
   grey reads as "off", and this is a live number that simply came from somewhere else. Uses the
   badge shape, not .est-warn, which is a 1.05em circle built for a single "?" character. */
.est-page .badge-est {
    background-color: rgba(240, 173, 78, 0.18);
    color: #a86a12;
    cursor: help;
    margin-left: 0.35rem;
}

.est-page .btn-action {
    background: none;
    border: none;
    color: var(--vml-blue);
    cursor: pointer;
    padding: 0;
    font-size: 0.85rem;
}

    .est-page .btn-action:hover {
        text-decoration: underline;
    }

/* A button that must be indistinguishable from the link beside it. .btn-action underlines only on
   hover, which made "Save to Share" read as a different kind of control than "Download". */
.est-page .btn-linklike {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--vml-blue);
    text-decoration: underline;
    cursor: pointer;
    /* Buttons default to vertical-align: middle, which sat this 2px above the baseline the
       neighbouring link sits on — enough to read as a different kind of control. */
    vertical-align: baseline;
}

    .est-page .btn-linklike:disabled {
        color: var(--vml-gray-dark);
        cursor: default;
    }

.est-page .row-actions {
    white-space: nowrap;
}

    .est-page .row-actions > * {
        margin-right: 0.9rem;
    }

.est-page .btn-secondary {
    background-color: var(--vml-white);
    border-color: #ccc;
    color: var(--vml-gray-dark);
}

/* ------------------------------------------- classification cell (Materials page)

   An unconfirmed classification is a *guess about the classification*, so the signal belongs
   on the classification box rather than next to the material name. Two cues, both quiet:
   an amber border with a left accent bar, and the word "suggested" sitting inside the box on
   the right.

   Paint order is the fiddly part. A positioned element paints above non-positioned siblings
   regardless of DOM order, so the watermark would cover the typed value. Giving the input
   `position: relative; z-index: 1` against the watermark's `z-index: 0` — and making the
   input's background transparent so the watermark shows through — puts the value on top and
   lets a long value run over the word, which is the intent. */

.est-group {
    position: relative;
    display: block;
}

.est-group input.form-control {
    position: relative;
    z-index: 1;
    background-color: transparent;
}

.est-group-flag {
    position: absolute;
    z-index: 0;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    /* Deliberately low contrast: it has to stay readable behind a long value that overlaps it,
       and it's a hint about state rather than a label for the field. */
    color: #e6cda6;
    pointer-events: none;
    user-select: none;
    white-space: nowrap;
}

.est-group.is-suggested {
    background-color: #fffcf4;
    border-radius: 4px;
}

    .est-group.is-suggested input.form-control {
        border-color: #e3b671;
        box-shadow: inset 3px 0 0 0 #e3b671;
    }

/* Row-level tint so a screen full of unconfirmed rows is scannable at a glance. */
.est-row-suggested td {
    background-color: #fffdf8;
}

/* --------------------------------------------------------------- bulk confirm bar */

.est-bulk {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    background-color: var(--vml-white);
    border: 1px solid var(--vml-gray-light);
    border-left: 3px solid #e3b671;
    border-radius: 5px;
    padding: 0.55rem 0.85rem;
    margin-bottom: 0.9rem;
    font-size: 0.88rem;
}

    .est-bulk .est-bulk-spacer {
        flex: 1 1 auto;
    }

    .est-bulk strong {
        color: var(--vml-black);
    }

.est-bulk-confirm {
    background-color: var(--vml-blue);
    border: 1px solid var(--vml-blue-dark);
    color: #fff;
    border-radius: 4px;
    padding: 0.3rem 0.8rem;
    font-size: 0.85rem;
    cursor: pointer;
}

    .est-bulk-confirm:hover {
        background-color: var(--vml-blue-dark);
    }

    .est-bulk-confirm:disabled {
        opacity: 0.6;
        cursor: not-allowed;
    }

.est-bulk-cancel {
    background: none;
    border: none;
    color: var(--vml-gray-dark);
    cursor: pointer;
    font-size: 0.85rem;
}

    .est-bulk-cancel:hover {
        text-decoration: underline;
    }

/* Plan picking: the commit button sits under each candidate's stats. */
.est-plan-actions {
    margin-top: 0.7rem;
}

    .est-plan-actions .btn {
        font-size: 0.9rem;
        padding: 0.35rem 0.9rem;
    }

/* On-demand export list - narrower than a data table, no header row. */
.est-export-table td {
    vertical-align: middle;
}

    .est-export-table td:first-child {
        white-space: nowrap;
    }
