﻿/*
* demo.css
* File include item demo only specific css only
******************************************************************************/

            .card {
                padding: 10px;
            }

            .template-customizer-open-btn {
                display: none !important;
            }

            .noDecoration{
                text-decoration:none!important;
                color:inherit;
            }

            .btn-primary {
                /*background-color:red!important;*/
            }
            .btn-mainpage {
                background-color: lightslategray;
                width: 165px;
                border-radius: 15px;
                text-decoration: none;
                color: white;
                margin: 5px;
            }

            .btn-mainpage:hover {
                background-color: lightgrey;
            }
            .cycoption{width:80%!important}

.nav-pills {
    width: 50%
}

.navs1 {
    display: flex;
    -ms-flex-direction: column !important;
    flex-direction: row;
    width: 100%
}

.nav-link.active {
    /* Active tab/pill follows the active app theme's accent (--ef-accent inherits from the
       html[data-app-theme] root); falls back to the Bootstrap primary on the default skin.
       Was a flat lightgray that ignored the theme. */
    background-color: var(--ef-accent, var(--bs-primary)) !important;
    color: #fff !important;
}

.nav-item {
    position: relative;
}

.money {
    text-align: right;
}

/*ELECTION PICKER*/
            .elecOptions {
                margin-top: -10px;
                margin-bottom: 10px !important;
            }

            .elecoption, .cycoption {
                color: black !important;
            }
            .CurrentCycle{
                /*background-color:yellow;*/
            }
            .selectedSubElection {
                text-decoration: underline;
                /*border: 2px solid white;*/
            }


/*TOGGLE SWITCH*/
            .switch {
            position: relative;
            display: inline-block;
            width: 60px;
            height: 34px;
            }

            /* Hide default HTML checkbox */
            .switch input {
            opacity: 0;
            width: 0;
            height: 0;
            }

            /* The slider */
            .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            -webkit-transition: .4s;
            transition: .4s;
            }

            .slider:before {
            position: absolute;
            content: "";
            height: 26px;
            width: 26px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            -webkit-transition: .4s;
            transition: .4s;
            }

            input:checked + .slider {
            background-color: #2196F3;
            }

            input:focus + .slider {
            box-shadow: 0 0 1px #2196F3;
            }

            input:checked + .slider:before {
            -webkit-transform: translateX(26px);
            -ms-transform: translateX(26px);
            transform: translateX(26px);
            }

            /* Rounded sliders */
            .slider {
            border-radius: 34px;
            }

            .slider:before {
            border-radius: 50%;
            }

/*SWITCH TABLE TO ROWS IN MOBILE VIEW*/
/*._mh-label {
    text-align:left !important;
}
._mh-value {
    text-align: right !important;
}*/
._mh-label,
._mh-value {
    display: flex;
    align-items: baseline !important;
    height: 100% !important;
    text-align: left !important;
}


table {
    width: 100%;
    border-collapse: collapse;
}

            @media (max-width: 820px) {
                /* Pair each _mh-label with the _mh-value next to it via a 2-col grid on the row.
                   Labels are injected by sideBySideMobileHeaders() in app.js at the same breakpoint. */
                table { width: 100%; border-collapse: collapse; }
                thead { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

                tbody tr {
                    display: grid;
                    grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
                    column-gap: 12px;
                    row-gap: 4px;
                    align-items: center;
                    margin-bottom: 12px;
                    border: 1px solid rgba(0,0,0,0.1);
                    border-radius: 6px;
                    padding: 10px 12px;
                    background-color: var(--ef-card-bg, #fff);
                    max-width: 100%;
                    overflow: hidden;
                }

                tbody td {
                    border: none;
                    padding: 4px 0;
                    min-width: 0;
                    overflow-wrap: anywhere;
                    word-break: break-word;
                }
                tbody td._mh-label {
                    font-weight: 600;
                    font-size: 0.78rem;
                    text-transform: uppercase;
                    letter-spacing: 0.04em;
                    color: var(--ef-muted-fg, #6b7280);
                    text-align: left;
                    /* sideBySideMobileHeaders copies computed <th> styles (including width)
                       inline onto this element. Force it back to grid-column sizing. */
                    width: auto !important;
                    max-width: 100% !important;
                    min-width: 0 !important;
                    white-space: normal !important;
                }
                tbody td._mh-value {
                    text-align: right;
                    padding-left: 0 !important;
                }
                /* Stop wide children (file inputs, preview images, textareas) from blowing out the card */
                tbody td._mh-value > *,
                tbody td._mh-value input,
                tbody td._mh-value textarea,
                tbody td._mh-value select,
                tbody td._mh-value img,
                tbody td._mh-value iframe {
                    max-width: 100%;
                    box-sizing: border-box;
                }
                tbody td._mh-value input[type="file"] { width: 100%; }
                tbody td._mh-value img { height: auto; }
                /* Select2 / jQuery-UI widgets often carry inline width from desktop render */
                tbody td._mh-value .select2-container,
                tbody td._mh-value .ui-widget {
                    width: 100% !important;
                    max-width: 100% !important;
                }
                /* Rows that don't get label-injected (e.g., the JS didn't run) fall back to centered */
                tbody tr:not(:has(._mh-label)) { display: block; }
                tbody tr:not(:has(._mh-label)) td { display: block; text-align: center; }
}
/*END OF SWITCH TABLE TO ROWS IN MOBILE VIEW*/


/*FOMATTING*/
            .hidden{display:none!important;}
            .text-align-right{
                text-align:right!important;
            }
            /* Generic reusable single-line truncation with ellipsis. Pair with a
               title="" attribute so the full text is available on hover. Used by the
               dashboard low-inventory list and item-detail vendor names. Width is
               capped to the containing column by default; override .ef-truncate's
               max-width inline or via a modifier where a different cap is needed. */
            .ef-truncate {
                display: inline-block;
                max-width: 100%;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                vertical-align: bottom;
            }
            .card.widget li > .d-flex.flex-column {
                flex: 1 1 auto;
                min-width: 0;
                width: auto;
            }
            .card.widget .apexcharts-canvas {
                margin-left: auto;
                margin-right: auto;
            }
            .centerContent {
                text-align: center !important;
                justify-content: center !important;
                /*display: flex !important;*/
                align-content: center !important;
                align-items: center !important;
            }
            /* Sidebar session-only current-election switcher (Site1.Master). The toggle
               shows the active election; clicking it collapses/expands the list of recent
               elections. Selecting one is a temporary, per-session view switch. */
            /* Hide the switcher while the sidebar is collapsed to its icon rail. The toggle is
               a wide, icon-less text button (the election name at font-size:large), so at rail
               width it has nothing to shrink to and renders as a stray fragment of text.
               The :not() chain is the THEME'S OWN contract for "collapsed and not currently
               hover-expanded" -- it is the exact prefix common-core.css uses on every
               .menu-item / .menu-block rule -- so the switcher reappears while the rail is
               hovered open, behaving like the rest of the menu instead of vanishing outright.
               The whole .ef-election-switcher row is hidden, not just the toggle: hiding the
               toggle alone would strand an already-expanded #efElectionSwitcherList below it
               with no way to close it. No !important needed -- four classes plus the row class
               out-rank Bootstrap's .row display:flex. */
            .layout-menu-collapsed:not(.layout-menu-hover):not(.layout-menu-offcanvas):not(.layout-menu-fixed-offcanvas) .ef-election-switcher {
                display: none;
            }
            /* Button treatment for the toggle. It replaces a DISABLED experiment that hard-coded
               a brick-red (#c0392b) tint: that read as an alert rather than a control, and being
               literal hex it looked wrong on the themes whose sidebar is dark (slate/usa/disco/
               synthwave). Everything here is a --ef-MENU-* token, not a body token, because the
               control lives inside .bg-menu-theme -- so it tracks the SIDEBAR's palette on all
               eight themes plus light/dark, which is what makes it legible on a dark rail.

               Restrained by intent: the resting state is a neutral recessed surface (the menu's
               own hover tint) so it reads as a control without competing with the nav items
               under it. The ACCENT appears only on hover/focus and while the list is open --
               i.e. on interaction and on state, never at rest. Same rule the KPI dashboard now
               follows.

               !important on color/background beats the Sneat .bg-menu-theme .menu-link rules,
               which set both at higher specificity than a bare class. */
            .ef-election-switcher-toggle.menu-link {
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 0.25rem;
                /* Sneat's .menu-link is flex:0 1 auto. That only shrinks the button if the
                   parent is a flex container -- .centerContent's display:flex is commented out
                   today, so this is insurance against it being switched back on. */
                width: 100%;
                padding: 0.5rem 0.75rem;
                /* Was inline font-size:large (~1.125rem), which wrapped "2025 General" onto two
                   lines in the sidebar's width. 1rem holds a typical election name on one. */
                font-size: 1rem;
                font-weight: 600;
                line-height: 1.3;
                color: var(--ef-menu-fg, #677788) !important;
                background-color: var(--ef-menu-hover-bg, rgba(0, 0, 0, 0.04)) !important;
                border: 1px solid var(--ef-menu-border, #d4d8dd);
                border-radius: 0.375rem;
                transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
            }
            .ef-election-switcher-toggle.menu-link:hover,
            .ef-election-switcher-toggle.menu-link:focus-visible,
            .ef-election-switcher-toggle.menu-link[aria-expanded="true"] {
                color: var(--ef-accent, var(--bs-primary)) !important;
                border-color: var(--ef-accent, var(--bs-primary));
            }
            /* Expand/collapse smoothness.
               Bootstrap animates height 0 -> scrollHeight and applies `overflow:hidden` ONLY
               while .collapsing is on. That temporarily makes the panel a block formatting
               context, so during the animation its children's vertical margins are counted in
               the measured height -- but the moment the transition ends and the panel goes to
               `height:auto` with overflow visible again, those margins collapse OUT of it and
               the real height changes. That mismatch is the snap at the end of the expand.
               Here it is worth ~3rem: the <hr> alone carries `margin: 1rem 0`, and the
               .menu-item rows (margin: .0625rem .938rem) collapse through the <ul>, which has
               no vertical padding or border to contain them.

               display:flow-root makes the panel a BFC in EVERY state, so the height it
               measures is the height it ends at. It cannot fight the hidden state:
               `.collapse:not(.show){display:none}` is two classes and out-ranks this one. The
               <hr>'s margin is then re-expressed as panel padding, which IS inside the
               measured box. */
            .ef-election-switcher-list {
                display: flow-root;
            }
            .ef-election-switcher-list > ul {
                margin: 0;
            }
            .ef-election-switcher-list > hr {
                margin: 0.5rem 0 0;
            }
            .ef-election-switcher-list.collapse.show,
            .ef-election-switcher-list.collapsing {
                padding-bottom: 0.5rem;
            }
            /* Slightly quicker than Bootstrap's .35s ease, on the standard material curve --
               a height transition that decelerates reads as smoother than a symmetric ease.
               will-change keeps the panel on its own layer for the duration instead of
               re-laying-out the sidebar each frame. */
            .ef-election-switcher-list.collapsing {
                transition: height 0.28s cubic-bezier(0.4, 0, 0.2, 1);
                will-change: height;
            }
            @media (prefers-reduced-motion: reduce) {
                .ef-election-switcher-list.collapsing {
                    transition: none;
                }
            }
            .ef-election-switcher-item.active > .menu-link {
                font-weight: 600;
            }
            .ef-election-switcher-item.active > .menu-link .ef-election-switcher-item-name::after {
                content: " \2713"; /* checkmark on the currently-active election */
            }
            .ef-election-switcher-item-date {
                font-size: 0.75rem;
            }
            .formsec {
                text-align: center;
                justify-content: center;
                display: flex;
                align-content: center;
                align-items: center;
            }
            .pull-right {
                float: right !important
            }

            .pull-none {
                float: none !important
            }

            .hidden {
                display: none;
            }
            .cursorPointer{cursor:pointer;}
            .initialsAlternate{
                width: 100px;
                height: 100px;
                text-align: center;
                align-content: center;
                font-size: xx-large;
                font-weight: 600;
            }
            .bx{cursor:pointer;}

            .buttonCard {
                position: sticky;
                top: 10px;
            }

.light-style .menu .app-brand.demo {
    height: 64px;
}

.dark-style .menu .app-brand.demo {
  height: 64px;
}

.app-brand-logo.demo {
  -ms-flex-align: center;
  align-items: center;
  -ms-flex-pack: center;
  justify-content: center;
  display: -ms-flexbox;
  display: flex;
  width: 30px;
  height: 30px;
}

.app-brand-logo.demo svg {
  width: 1.7rem;
  height: 1.7rem;
}

.app-brand-text.demo {
  font-size: 1.75rem;
  letter-spacing: -0.45px;
}

/* ! For .layout-navbar-fixed added fix padding top tpo .layout-page */
.layout-navbar-fixed .layout-wrapper:not(.layout-without-menu) .layout-page {
  padding-top: 64px !important;
}

/* Navbar page z-index issue solution */
.content-wrapper .navbar {
  z-index: auto;
}

/*
* Content
******************************************************************************/

.demo-blocks > * {
  display: block !important;
}

.demo-inline-spacing > * {
  margin: 1rem 0.375rem 0 0 !important;
}

/* ? .demo-vertical-spacing class is used to have vertical margins between elements. To remove margin-top from the first-child, use .demo-only-element class with .demo-vertical-spacing class. For example, we have used this class in forms-input-groups.html file. */
.demo-vertical-spacing > * {
  margin-top: 1rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing.demo-only-element > :first-child {
  margin-top: 0 !important;
}

.demo-vertical-spacing-lg > * {
  margin-top: 1.875rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing-lg.demo-only-element > :first-child {
  margin-top: 0 !important;
}

.demo-vertical-spacing-xl > * {
  margin-top: 5rem !important;
  margin-bottom: 0 !important;
}
.demo-vertical-spacing-xl.demo-only-element > :first-child {
  margin-top: 0 !important;
}

.rtl-only {
  display: none !important;
  text-align: left !important;
  direction: ltr !important;
}

[dir='rtl'] .rtl-only {
  display: block !important;
}

/*
* Layout demo
******************************************************************************/

.layout-demo-wrapper {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
  margin-top: 1rem;
}
.layout-demo-placeholder img {
  width: 900px;
}
.layout-demo-info {
  text-align: center;
  margin-top: 1rem;
}

.hidden {
display:none;
}




/* Table Mobile layout */
.buttonTD {
    text-align: center;
    justify-content: center;
    /*padding: 5px !important;*/
    min-width: 150px;
}
    .buttonTD .d-inline-block {
        width:100%;
    }

    @media (max-width: 820px) {
        .buttonTD, .buttonTD .d-inline-block {
            justify-content: space-between;
            align-items: center;
        }
        ._mh-value .btn-icon {
            font-size: 1.7rem;
        }
    }

/* Theme-aware logos.
   Each brand logo is rendered twice -- a light (.ef-logo-light) and a dark
   (.ef-logo-dark) <img>/<image> using its *_dark variant. CSS shows only the
   one matching the current style and hides the other. The html.dark-style
   class is toggled live by the Sneat TemplateCustomizer, so this reacts
   instantly and needs no JS. app.css is loaded by every shell (including the
   logged-out pages), so logos swap everywhere. */
html:not(.dark-style) .ef-logo-dark { display: none !important; }
html.dark-style .ef-logo-light { display: none !important; }

/* Themes whose sidebar (bg-menu-theme, where the brand logo lives) is dark or
   saturated even in their LIGHT-style variant, so the dark-text wordmark is
   unreadable. Force the white (*_dark) logo for these regardless of light/dark
   skin. Equal specificity to the two rules above, so ordering after them wins. */
html[data-app-theme="slate"] .ef-logo-light,
html[data-app-theme="usa"] .ef-logo-light,
html[data-app-theme="synthwave"] .ef-logo-light,
html[data-app-theme="disco"] .ef-logo-light { display: none !important; }
html[data-app-theme="slate"] .ef-logo-dark,
html[data-app-theme="usa"] .ef-logo-dark,
html[data-app-theme="synthwave"] .ef-logo-dark,
html[data-app-theme="disco"] .ef-logo-dark { display: inline !important; }

/*
* Content footer — pin flush to the very bottom of the page.
* The theme's .content-wrapper uses `justify-content: space-between` (core.css),
* which distributes free space in the flex column and lets the footer drift up a
* little at full scroll instead of sitting flush. Left-pack the column and push
* the footer down with margin-top:auto so it always hugs the bottom edge.
******************************************************************************/
.content-wrapper {
  justify-content: flex-start;
}
.content-wrapper > .content-footer {
  margin-top: auto;
}
/* Sticky-footer fill: force the content column to be at least a full viewport tall so the
 * footer hugs the bottom edge and no html/body canvas shows beneath it. The theme relies on
 * flex `align-items: stretch` (on .layout-container) to make this column fill 100vh, but on
 * short pages it was collapsing to content height, leaving the reported gap under the footer.
 * .layout-page holds the navbar + .content-wrapper, so 100vh here (not on .content-wrapper)
 * avoids double-counting the navbar and never forces a scrollbar. */
.layout-content-navbar .layout-page {
  min-height: 100vh;
}
/* The document renders ~15px taller than the app shell (a stray sliver of height from
 * injected chrome / trailing nodes), so the bare <html> canvas shows as a thin band under
 * the footer. elementFromPoint on the band returns <html>, i.e. nothing is actually there.
 * Zero any stray body/html margin that could add to it, and paint the html canvas with the
 * theme body background so the sliver is seamless instead of a contrasting gap. */
html, body {
  margin: 0;
}
html {
  background-color: var(--bs-body-bg);
}
/* The theme's .content-backdrop div sits in the DOM AFTER the footer inside .content-wrapper.
 * It's meant to be a fixed, full-screen overlay (only visible with .show, e.g. the mobile menu
 * backdrop), but while inactive it was taking normal-flow space below the footer and revealing
 * the body background as a stray gap beneath it. Keep it out of flow unless actively shown. */
.content-wrapper > .content-backdrop:not(.show) {
  display: none;
}

/* Footer "made by ElectionFlow" wordmark — swap the text link for the logo image, sized
 * to sit inline with the copyright text. ef-logo-light / ef-logo-dark are toggled by the
 * active theme (same pattern as the sidebar brand). */
.ef-footer-logo {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}
.ef-footer-logo img {
  height: 30px;
  width: auto;
  vertical-align: middle;
}

/* Shared list pager (assets/js/ef-list-pager.js) — search + 10/25/50/Show-all paging
 * under the items list and the storage-locations list. One home for the styling;
 * don't re-paste these rules into page <style> blocks. */
.ef-pager { font-size: .875rem; gap: 8px; }
.ef-pager .ef-pager-info { color: #6b7280; }
.ef-pager .ef-pager-controls { display: flex; align-items: center; gap: 8px; }
.ef-pager select.form-select { width: auto; display: inline-block; }

/* List-page primitives shared by the standard list pages (items DashBoard,
 * supplyrequests, InternalSupplyRequests, MyRequests): the search box sizing, the
 * fixed table layout the per-column inline widths rely on, and the below-lg column
 * squeeze. One home — don't re-paste these into page <style> blocks.
 * .ef-dash-shrink pairs with a th's inline width and overrides it below lg so the
 * Item column stays legible (the !important is what beats the inline width);
 * .dash-shrink is the legacy alias DashBoard.aspx still uses. */
.ef-list-search { max-width: 320px; margin-bottom: 0; }
.ef-list-table { table-layout: fixed; width: 100%; }
@media (max-width: 991.98px) {
  .ef-dash-shrink, .dash-shrink { width: 100px !important; }
}

/* Request-queue tables (supplyrequests / InternalSupplyRequests / MyRequests) size
 * their columns as PERCENTAGES of the card — table-layout:fixed scales them with
 * the screen width and the unsized Item column absorbs the remainder — instead of
 * the fixed px widths + .ef-dash-shrink squeeze the items DashBoard uses (fixed px
 * sums overflowed the card on laptop widths and starved the Item column to nothing).
 * .ef-req-scroll goes on the .card that wraps the table: below the table's floor
 * width the CARD scrolls sideways rather than the table running off the card/page.
 * The min-widths are gated above the 820px stacked-card breakpoint (SWITCH TABLE TO
 * ROWS, top of this file) so they can never force a sideways scroll on phones,
 * where rows render as stacked cards instead. */
.ef-req-scroll { overflow-x: auto; }
@media (min-width: 821px) {
  .ef-req-scroll > .ef-list-table { min-width: 760px; }
  .ef-req-scroll > .ef-myr-table { min-width: 560px; }
  /* Item picker modal (InternalSupplyRequestEntry) — same guard, four columns
     instead of eight, so a lower floor. Below 821px the rows stack as cards and
     the floor is off, exactly as for the request lists. */
  .ef-req-scroll > .ef-picker-table { min-width: 620px; }
  /* Location step (LocationSupplyRequest) — three columns, one of them a building name, so a
     lower floor than the item picker's four. Off below 821px like every other floor here. */
  .ef-req-scroll > .ef-lsr-locpick-table { min-width: 520px; }
  /* Request lines grid (LocationSupplyRequest batch mode) — the picker's four columns plus a
     quantity input, so a floor just above the picker's. Off below 821px like the rest. */
  .ef-req-scroll > .ef-lsr-lines-table { min-width: 680px; }
  /* Return count (LocationReturns) — three columns, one of them a number input, so the lowest
     floor of the set. Off below 821px, where the rows stack as cards. */
  .ef-req-scroll > .ef-lrt-table { min-width: 480px; }
  /* Returns board (Admin/ReturnsDashboard) — seven columns, so the highest floor of this set. */
  .ef-req-scroll > .ef-rtd-table { min-width: 900px; }
  /* Supply-request KPI reports (SupplyRequestDashboard): the summary level is three
     narrow columns, the detail level is eight, so they get different floors. Both are
     off below 821px, where the rows stack as cards. */
  .ef-req-scroll > .ef-srk-summary-table { min-width: 420px; }
  .ef-req-scroll > .ef-srk-detail-table { min-width: 900px; }
}

/* Widget-dashboard tile (.card.widget.h-100 — see docs/page-standards.md): hover lift,
 * compact uppercase header, tight body. Hoisted from Default.aspx's page <style> block
 * when SupplyRequestDashboard.aspx became the second widget dashboard; themes.css
 * recolors it under html[data-app-theme]. The h3 !importants beat Default.aspx's
 * page-scoped h1-h3 centering rule — keep them. */
.widget {
  cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 0.5rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.widget:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
  border-color: rgba(0, 0, 0, 0.15);
}
.widget .card-header {
  background: transparent;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  padding: 0.6rem 1rem;
}
.widget .card-header h3 {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #6b7280;
  margin: 0;
  text-align: left !important;
  width: auto !important;
}
.widget .card-body {
  padding: 0.75rem 1rem;
}

/* Accent-bordered table column headers (meeting item: match the Purchase Information
 * treatment on the item page). Add .ef-accent-table to a .table to give its header row
 * an accent underline; the color tracks the active app theme via --ef-accent and falls
 * back to Bootstrap primary on the default skin. */
.ef-accent-table thead th {
  border-bottom: 2px solid var(--ef-accent, var(--bs-primary));
}

/* Skin-following logo pair (light/dark swap driven ONLY by html.dark-style).
 * Distinct from .ef-logo-light/.ef-logo-dark, which several app themes force to the
 * white variant because the SIDEBAR is dark — that forcing would make the logo vanish
 * on light surfaces like a modal header or dashboard card, so these classes ignore
 * data-app-theme on purpose. */
html:not(.dark-style) .ef-skin-logo-dark { display: none !important; }
html.dark-style .ef-skin-logo-light { display: none !important; }

/* Small ElectionFlow mark auto-added to every iframe-dialog title (createBootstrapModal). */
.ef-dlg-title-logo {
  height: 20px;
  width: auto;
  margin-right: 8px;
  vertical-align: text-bottom;
}

/* Dashboard countdown banner: the ElectionFlow mark is docked INLINE next to the
 * "Election Day" title (see Default.aspx) rather than absolutely placed, so it never
 * reserves side padding that would crowd/overflow the four countdown blocks on phones.
 * The countdown row now gets the full banner width; the number scaling below (clamp in
 * Site1.Master's .ef-countdown-big rules) keeps it inside the card. */
.ef-banner-logo {
  height: 28px;
  width: auto;
  opacity: 0.9;
  vertical-align: text-bottom;
}
@media (max-width: 575.98px) {
  .ef-banner-logo { height: 22px; }
}
/* Read-only aggregate "Total Quantity on Hand" input on item pages (InventoryManager,
 * KeyManager). Disabled + gray so it reads as computed output, not an editable field;
 * the value is the sum of the per-location quantities (UCstorageLocation.getTotalCount). */
.ef-totalcount-input,
.form-control.ef-totalcount-input:disabled {
  background-color: #eeeeee;
}

/* Page tab strip — the folder-tab treatment, shared. Add .ef-tabs to a `ul.nav.nav-pills`
 * whose items are mutually-exclusive VIEWS of the same page; the active item still uses
 * Bootstrap's own .active, so no markup beyond the one container class.
 *
 * This started as a page-local block on Admin/AppSettings.aspx and is now the app-wide
 * treatment for tabbed pages (AppSettings, ActivityLog, Users, UserPagePermissions,
 * Reports). Square-topped tabs sitting on a rule read as "these are views of one page",
 * which fully-rounded pills do not.
 *
 * DO NOT put this on a nav-pills strip that is NOT tabs — several exist and are deliberately
 * left as plain pills: the module-nav trio in UCnavOptions-*.ascx (those navigate to other
 * pages), the Back-button bars on PalletManager / SupplyRequestHistory, and the Add-link bar
 * on StorageLocations. Folder tabs there would promise a view switch that isn't there.
 *
 * Colour: the neutrals follow the theme (--ef-muted-fg / --ef-card-border), and the active
 * fill is --ef-tab-active-bg, which no theme sets today so it resolves to the #0F4C81 navy
 * this treatment has always used. That keeps the look identical to the AppSettings original
 * while giving themes a single hook to override, rather than the old hard-coded literal.
 * !important on the active fill beats Bootstrap's `.nav-pills .nav-link.active`, which sets
 * the brand colour at equal specificity. */
.ef-tabs {
  border-bottom: 1px solid var(--ef-card-border, #e5e7eb);
  margin-bottom: 14px;
}
.ef-tabs .nav-link {
  color: var(--ef-muted-fg, #6b7280);
  font-size: 13px;
  font-weight: 600;
  padding: 8px 14px;
  border: 0;
  border-radius: 6px 6px 0 0;
  cursor: pointer;
}
.ef-tabs .nav-link:hover {
  color: var(--ef-tab-active-bg, #0F4C81);
}
.ef-tabs .nav-link.active,
.ef-tabs.nav-pills .nav-link.active {
  color: #fff !important;
  background-color: var(--ef-tab-active-bg, #0F4C81) !important;
}

/* Second-level tabs, for a page whose top-level tab splits into related-but-separate
 * views (Inventory -> Inventory / Supply Requests on Admin/AppSettings + Reports).
 * Add .ef-subtabs to a `ul.nav.nav-pills` the same way as .ef-tabs.
 *
 * Deliberately LIGHTER than .ef-tabs so the hierarchy is legible at a glance: smaller
 * text, fully rounded (not folder-shaped — the folder rule belongs to the level above),
 * and the active one is a soft tint with coloured text rather than a solid fill. If both
 * levels were solid navy folders you couldn't tell which row you were reading.
 *
 * A strip is only rendered when there are at least TWO sub-tabs to choose between; one
 * sub-tab is not a choice, so the page shows its contents with no strip at all. */
.ef-subtabs {
  margin-bottom: 12px;
  gap: 0.25rem;
}
.ef-subtabs .nav-link {
  color: var(--ef-muted-fg, #6b7280);
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
}
.ef-subtabs .nav-link:hover {
  color: var(--ef-tab-active-bg, #0F4C81);
  background-color: var(--ef-hover-bg, rgba(0, 0, 0, 0.04));
}
.ef-subtabs .nav-link.active,
.ef-subtabs.nav-pills .nav-link.active {
  color: var(--ef-tab-active-bg, #0F4C81) !important;
  background-color: var(--ef-hover-bg, rgba(0, 0, 0, 0.06)) !important;
  border-color: var(--ef-card-border, #e5e7eb);
}

/* Status-tab switcher — the full-width pill strip that filters a list by status
 * (New / Partial / Denied / Completed / All on InternalSupplyRequests.aspx). The active
 * pill is marked by JS comparing each option's href against the current URL, which adds
 * .ef-is-active. One home for the styling; don't re-paste these rules into page <style>
 * blocks. Every page is on this primitive now — the legacy local copies of these rules
 * (.viewSwitcher / .viewOption / .activeOption on supplyrequests.aspx,
 * SupplyRequestHistory.aspx, Admin/ActivityLog.aspx) have been deleted; don't reintroduce
 * those names. */
.ef-status-switcher {
  margin-top: 5px;
  cursor: pointer;
  border: solid 1px gray;
  border-radius: 10px;
  width: 100%;
  justify-content: space-between;
  display: flex;
}
.ef-status-switcher-opt {
  width: 200px !important;
  text-align: center;
  padding: 3px;
  height: 30px;
  color: black;
  border-radius: 10px;
}
.ef-status-switcher-opt:hover,
.ef-status-switcher-opt.ef-is-active {
  background-color: lightgrey;
  color: white;
}

/* A sticky action card with no visible buttons left in it. Set by the empty-.buttonCard guard
 * in assets/js/app.js (which also clears it again when a button reappears), so an action card
 * whose only buttons are Visible="false" / .hidden stops painting as an empty bordered box.
 * !important because .card carries its own display from the theme. */
.buttonCard.ef-buttoncard-empty {
  display: none !important;
}

/* ...and with the card gone, the narrow col-md-2 it had to itself is dead space, so the
 * detail-page row collapses it and lets the CONTENT columns take the width back -- whatever
 * shape the page uses: col-md-5 / col-md-5 / col-md-2 reads as a clean half each, and the
 * commoner col-md-10 / col-md-2 goes full width. Both markers are set by the same guard in
 * app.js and removed the moment a button reappears, so the page's real column classes are
 * never rewritten. The compound selectors out-rank Bootstrap's own .col-md-N widths without
 * needing !important, and the width only changes from md up -- below that the columns are
 * already full-width stacks. */
.ef-buttoncol-empty {
  display: none !important;
}
@media (min-width: 768px) {
  [class*="col-md-"].ef-buttoncol-grown {
    flex: 0 0 auto;
  }
  /* New span = old span * 12/10, i.e. the freed two columns shared out in proportion, which
   * is simply span * 10%: col-md-5 / col-md-5 / col-md-2 reads as a clean half each, and the
   * single-content-column layout the detail pages use (col-md-10 + col-md-2 -- Admin/
   * LocationDetail.aspx, PrecinctDetail.aspx) goes full width instead of leaving the old
   * action column as a gap on the right. Listed per span rather than computed so the marker
   * class stays the ONLY thing JS touches. */
  .col-md-4.ef-buttoncol-grown  { width: 40%; }
  .col-md-5.ef-buttoncol-grown  { width: 50%; }
  .col-md-6.ef-buttoncol-grown  { width: 60%; }
  .col-md-7.ef-buttoncol-grown  { width: 70%; }
  .col-md-8.ef-buttoncol-grown  { width: 80%; }
  .col-md-9.ef-buttoncol-grown  { width: 90%; }
  .col-md-10.ef-buttoncol-grown { width: 100%; }
}

/* Label-left / switch-right row for a boolean on a detail page -- the shape
 * Inventory/Inventory/InventoryManager.aspx uses for "Exclude from Audits" and "HAVA
 * Purchase", extracted from the identical inline style="" copies those two carry so a new
 * toggle row is one class instead of four declarations. The switch itself is the app-wide
 * .toggleSwitch primitive (wired up in Site1.Master / Dlg.Master), not Bootstrap's
 * .form-switch -- asp:CheckBox puts CssClass on its wrapper span, which is exactly the
 * element that jQuery turns into the slider. */
.ef-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 15px;
}

/* A .row whose columns must line up with the full-width fields ABOVE and BELOW it.
 *
 * The Sneat theme's .row carries the gutter as PADDING on the columns but drops Bootstrap's
 * compensating negative margin on the row itself, so a plain .row nested inside a .card-body
 * indents its first column by half a gutter and outdents nothing at the right -- a City /
 * State / ZIP line no longer starts where the Address box above it does. Pulling the half
 * gutter back off both edges restores stock Bootstrap behaviour for the rows that need it,
 * without touching the theme's .row for every other page. */
.ef-row-flush {
  margin-left: calc(var(--bs-gutter-x, 1.625rem) * -0.5);
  margin-right: calc(var(--bs-gutter-x, 1.625rem) * -0.5);
}

/* Reports/ReportFrame.aspx report viewport. The wrapper clips and positions; the frame fills
 * it absolutely. 600px is only the pre-script fallback height -- adjustIframeHeight overwrites
 * the wrapper's height inline once it can measure the viewport, and on desktop/tablet
 * scaleIframe overwrites the frame's own width/height/transform inline to shrink a paper-sized
 * report into the column. Inline styles win over these rules, which is what makes that work. */
.ef-reportframe-wrapper {
  position: relative;
  width: 100%;
  height: 600px;
  overflow: hidden;
}
.ef-reportframe-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* Phone: the frame holds the ORDINARY screen render, not a sheet of paper, so it is shown 1:1
 * -- scaleIframe returns before writing a transform. Declared anyway so the no-scale state is
 * stated where the rest of the geometry lives rather than only implied by an early return. */
.ef-reportframe-screenonly .ef-reportframe-frame {
  transform: none;
}

/* Reports/ReportFrame.aspx opened INSIDE a dialog (the dashboard's Pick List / Delivery List
 * buttons). Its actions move onto the dialog footer, so the in-page col-md-2 action column is
 * redundant -- hide it and give the report the full width. The marker class is added by
 * ReportFrame's own script only when it detects it is framed; the full-page view is untouched.
 * The [class*="col-md-"] compound out-ranks Bootstrap's own col-md-10 width. */
.ef-reportframe-indialog .ef-reportframe-actions {
  display: none;
}
@media (min-width: 768px) {
  .ef-reportframe-indialog [class*="col-md-"].ef-reportframe-view {
    flex: 0 0 auto;
    width: 100%;
  }
}

/* "(N Remain)" under a partially-filled request's quantity. Block, so it takes its own line
 * instead of wrapping mid-parenthetical ("2 (2" / "Remain)") in the narrow Quantity column;
 * it inherits the cell's alignment, so it stacks directly under the requested amount. Muted
 * and smaller because the requested amount is the primary figure. Shared by all four request
 * lists (external queue, internal queue, My Requests, History). */
.ef-req-remain {
  display: block;
  /* nowrap matters as much as the block: the Quantity column is narrow enough that
     "(3 Remain)" otherwise breaks again into "(3" / "Remain)" on its own line. */
  white-space: nowrap;
  font-size: 0.8rem;
  color: var(--ef-muted-fg, #6b7280);
}

/* One <tr> per record in the request lists: a hairline border + gap so each row reads as
 * its own band rather than a dense grid. Shared by the request lists (older pages call it
 * .infoline in their own <style> blocks — same rules). */
.ef-request-row {
  margin-bottom: 5px;
  border: 1px solid #adadad;
}

/* Item picker (the "Choose Item" modal on Inventory/Inventory/InternalSupplyRequestEntry.aspx
 * and SupplyRequestEntry.aspx -- BOTH entry forms host the same picker).
 * The whole row is the hit target -- there is no per-row button -- so it needs the pointer
 * cursor and a hover band to read as clickable. Kept here rather than in the page because a
 * pick-an-item modal is the sort of thing the next entry form will want too. */
.ef-picker-row {
  cursor: pointer;
}
.ef-picker-row:hover {
  background-color: rgba(var(--bs-primary-rgb, 90, 141, 238), 0.08);
}
/* Column widths for the picker's four columns (Item / Category / On Hand / Position). The
 * table carries .ef-list-table's table-layout:fixed, so these are what shape it -- Item
 * takes the remainder. They lived as identical inline style="width:.." attributes in BOTH
 * entry forms, which made them a duplicated component layout rather than a one-off. */
.ef-picker-table th:nth-child(1) { width: 43%; }
.ef-picker-table th:nth-child(2) { width: 20%; }
.ef-picker-table th:nth-child(3) { width: 12%; }
.ef-picker-table th:nth-child(4) { width: 25%; }
/* Sideways-scroll guard is the shared .ef-req-scroll primitive (see its min-width
   block below) — the picker just adds its own floor there. No separate class. */

/* REQUEST LINES GRID on LocationSupplyRequest.aspx (batch mode) — the picker's columns plus a
 * Request column of quantity inputs. A NEW location request is one save covering several
 * items (one Supply_Request row per filled line), so the rows are NOT clickable pickers —
 * no .ef-picker-row — the input is the interaction. Same fixed-layout width discipline. */
.ef-lsr-lines-table th:nth-child(1) { width: 33%; }
.ef-lsr-lines-table th:nth-child(2) { width: 17%; }
.ef-lsr-lines-table th:nth-child(3) { width: 11%; }
.ef-lsr-lines-table th:nth-child(4) { width: 24%; }
.ef-lsr-lines-table th:nth-child(5) { width: 15%; }
/* Right-aligned and capped: a quantity is a handful of digits, and a full-width number box
   in a fixed-layout column reads as a text field. margin-left:auto keeps it on the column's
   right edge where the On Hand numbers already sit. */
.ef-lsr-line-qty {
  max-width: 110px;
  margin-left: auto;
  text-align: right;
}

/* ---- Notes modal theming (.ef-notes-modal) ----
 * The UCCommentChat notes modal's look, hoisted from InventoryManager.aspx's page <style>
 * block when Admin/LocationDetail.aspx became the second notes surface. Accent touches are
 * always on (falling back to Bootstrap primary on the default skin); the background textures
 * + surface colors engage only when an app theme is active, keying off the same vars as the
 * navbar/footer. Add the class to any modal hosting UCCommentChat. */
.ef-notes-modal .modal-header { border-bottom: 2px solid var(--ef-accent, var(--bs-primary)); }
.ef-notes-modal .newNoteHeading { color: var(--ef-accent, var(--bs-primary)); font-weight: 600; }
.ef-notes-modal .newNoteDivider { display: none; }
.ef-notes-modal .commentbox { border-left: 3px solid var(--ef-accent, var(--bs-primary)); }
.ef-notes-modal .newNoteSection,
.ef-notes-modal .previousComments {
  background: color-mix(in srgb, var(--ef-accent, var(--bs-primary)) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--ef-accent, var(--bs-primary)) 22%, transparent);
  border-left: 3px solid var(--ef-accent, var(--bs-primary));
  border-radius: 10px;
  padding: 12px 14px;
}
/* previousComments scrolls internally, so keep a little right padding for the scrollbar
   and a top margin separating the log card from the New Note card above it. */
.ef-notes-modal .previousComments { padding-right: 8px; margin-top: 4px; }
.ef-notes-modal .noteCatBadge {
  background: color-mix(in srgb, var(--ef-accent, var(--bs-primary)) 16%, transparent);
  color: var(--ef-accent, var(--bs-primary));
  border: 1px solid color-mix(in srgb, var(--ef-accent, var(--bs-primary)) 35%, transparent);
}
/* Theme-only: pull the modal onto the active theme's background texture + surfaces. */
html[data-app-theme] .ef-notes-modal .modal-content {
  background: var(--ef-body-bg-pattern, var(--ef-body-bg));
  border: 1px solid var(--ef-menu-border);
  color: var(--ef-body-fg);
}
html[data-app-theme] .ef-notes-modal .modal-title { color: var(--ef-heading-fg, var(--ef-body-fg)); }
html[data-app-theme] .ef-notes-modal .commentbox {
  background: var(--ef-card-bg);
  color: var(--ef-body-fg);
  box-shadow: var(--ef-card-shadow, 0 2px 5px 2px rgba(0,0,0,.15));
}
html[data-app-theme] .ef-notes-modal .commentername { color: var(--ef-heading-fg, var(--ef-body-fg)); }
html[data-app-theme] .ef-notes-modal .commentdatetime { color: var(--ef-muted-fg, #888); }

/* Navbar alert for the System > Location Returns staging position (Site1.Master): rendered
 * only while it holds units, links to Admin/ReturnsDashboard.aspx. Amber-toned so it reads
 * as "needs attention" without stealing the accent the Add buttons own; --ef-accent-warm is
 * an optional theme var, so the literal fallback carries the default skin. */
.ef-navbar-returns {
  margin-right: 0.75rem;
}
.ef-navbar-returns-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: 999px;
  border: 1px solid currentColor;
  color: var(--ef-accent-warm, #b07714);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.1;
  text-decoration: none !important;
  white-space: nowrap;
}
.ef-navbar-returns-pill:hover,
.ef-navbar-returns-pill:focus {
  color: var(--ef-accent-warm, #b07714);
  background-color: var(--ef-hover-bg, rgba(0, 0, 0, 0.05));
}

/* LOCATION STEP on Inventory/Inventory/LocationSupplyRequest.aspx — the first screen of that
 * dialog on the authenticated route: which of this election's polling places / EV sites is the
 * request for. Rows reuse .ef-picker-row above (whole row clickable, pointer + hover band), so
 * only the three column widths are new; .ef-list-table's table-layout:fixed is what makes them
 * bind, and the Location column takes the remainder because a building name is the longest
 * value here. Its .ef-req-scroll floor sits in that primitive's block below, like the picker's. */
.ef-lsr-locpick-table th:nth-child(1) { width: 22%; }
.ef-lsr-locpick-table th:nth-child(3) { width: 20%; }
.ef-lsr-locstep-sub { margin-bottom: 0.75rem; text-align: center; }

/* Required marker on the location supply request. Quantity and Urgency carry it; Reason says
   "(optional)" in words instead, because an asterisk on two of three fields only tells you which are
   required if you already know the convention -- spelling out the exception removes the guess. */
.ef-lsr-req {
  color: var(--bs-danger, #dc3545);
  font-weight: 700;
}

/* CENTRED HEADERS on the location supply request (Inventory/Inventory/LocationSupplyRequest.aspx).
 * The place being requested for, and the item chosen, are the two things whoever opened the link has
 * to confirm, so each sits in the MIDDLE of its card. The election + Change link and the Choose Item
 * button ride the right edge out of flow, which is what lets the text centre on the card instead of
 * centring on whatever space those leave -- the same trick as .ef-srl-header and the navbar countdown.
 * On a narrow screen the absolute pieces would overlap the heading, so below md they drop back into
 * flow underneath it. */
.ef-lsr-location-inner,
.ef-lsr-item-inner {
  position: relative;
  text-align: center;
  min-height: 2.25rem;
}
.ef-lsr-location-right,
.ef-lsr-item-inner .ef-lsr-choose-btn {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}
@media (max-width: 767.98px) {
  .ef-lsr-location-right,
  .ef-lsr-item-inner .ef-lsr-choose-btn {
    position: static;
    transform: none;
    margin-top: 0.5rem;
    justify-content: center;
  }
  .ef-lsr-item-inner .ef-lsr-choose-btn { display: block; margin-left: auto; margin-right: auto; }
}

/* CLOSE-OF-ELECTION RETURN COUNT (Inventory/Inventory/LocationReturns.aspx,
 * docs/location-returns-rollover.md) -- the public form a poll worker fills in at close. Column
 * widths again because .ef-list-table is table-layout:fixed, and the Supply column takes the
 * remainder; its .ef-req-scroll floor is in that primitive's block above. The count box is capped
 * and pushed right so the typed number sits under the "you were sent" figure it is being compared
 * with -- on a phone this is somebody entering numbers on a clipboard, so the two columns lining up
 * matters more than filling the cell. Every other ef-lrt-* class on that page is an identity hook
 * with no styling of its own, per the convention. */
.ef-lrt-table th:nth-child(2) { width: 22%; }
.ef-lrt-table th:nth-child(3) { width: 24%; }
.ef-lrt-count {
  max-width: 8rem;
  margin-left: auto;
}
.ef-lrt-intro { margin-bottom: 0.75rem; }

/* RETURNS BOARD (Admin/ReturnsDashboard.aspx, docs/location-returns-rollover.md). Column widths
 * because .ef-list-table is table-layout:fixed; the unsized Location column absorbs the remainder.
 * Percentages, not px, so the board scales the way the request queues do -- its .ef-req-scroll floor
 * is in that primitive's block above. */
.ef-rtd-table th:nth-child(1) { width: 16%; }
.ef-rtd-table th:nth-child(3) { width: 14%; }
.ef-rtd-table th:nth-child(4) { width: 10%; }
/* Status holds one short pill ("Waiting", "Counted", "Returned uncounted") and an optional name
   underneath, so it needs far less than the 15% it started with -- the freed width goes to the
   unsized Location column, which is the one holding a building name. */
.ef-rtd-table th:nth-child(5) { width: 11%; }
.ef-rtd-table th:nth-child(6) { width: 9%; }
.ef-rtd-table th:nth-child(7) { width: 12%; }
/* The pill sizes to its text; without this it stretched to the cell and the column looked oversized
   even after narrowing it. */
.ef-rtd-td-status .ef-rtd-pill { max-width: 100%; }

/* Status pill. Same shape as the Locations list's cell pills and the same reasoning about colour:
 * everything comes from theme tokens so all four states read on every skin in light and dark.
 * The states are ordered by what the office has to DO about them -- "due now" is the only one that
 * is a call to action, so it is the only one that gets the accent fill. */
.ef-rtd-pill {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 1px 9px;
  border-radius: 10rem;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  vertical-align: bottom;
}
.ef-rtd-pill-due {
  color: var(--ef-accent-fg, #fff);
  background-color: var(--ef-accent, var(--bs-primary));
  border: 1px solid var(--ef-accent, var(--bs-primary));
}
.ef-rtd-pill-counted {
  color: var(--ef-accent, var(--bs-primary));
  background-color: var(--ef-menu-hover-bg, rgba(90, 141, 238, 0.08));
  border: 1px solid var(--ef-accent, var(--bs-primary));
}
/* Counting open = today is the site's last day of voting, so the form is live and the automatic
   return has not taken over yet. Accent OUTLINE, not fill: it is a live window the office watches,
   where "Due now" is the one that needs acting on. */
.ef-rtd-pill-open {
  color: var(--ef-accent, var(--bs-primary));
  background-color: transparent;
  border: 1px solid var(--ef-accent, var(--bs-primary));
}
/* Reopened by the office. Dashed accent, like the other "somebody is still deciding" pills in this
   app (Prospective on the Locations list): the row is deliberately out of the automatic return's
   hands until a human closes it. */
.ef-rtd-pill-reopened {
  color: var(--ef-accent, var(--bs-primary));
  background-color: transparent;
  border: 1px dashed var(--ef-accent, var(--bs-primary));
}
.ef-rtd-pill-defaulted,
.ef-rtd-pill-waiting {
  color: var(--ef-muted-fg, #6b7280);
  background-color: transparent;
  border: 1px solid var(--ef-card-border, #d4d8dd);
}
/* Uncounted returns need reconciling by hand, so the pill is dashed: provisional, not finished --
   the same "still being decided" language the Prospective pill uses on the Locations list. */
.ef-rtd-pill-defaulted { border-style: dashed; }

/* Roll-up tiles above the board. Deliberately MONOCHROME, matching the supply-request KPI cards:
   the value carries weight, not colour, because this app reserves accent for actions. */
.ef-rtd-tile { padding: 12px 14px; height: 100%; }
.ef-rtd-tile-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ef-muted-fg, #6b7280);
}
.ef-rtd-tile-value {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ef-heading-fg, var(--ef-body-fg, #516377));
}
.ef-rtd-tile-note { font-size: 11px; color: var(--ef-muted-fg, #6b7280); }

/* ED / EV sub-tab counts. Plain inline text, deliberately NOT a Bootstrap `.badge`: this page renders
   a .navs strip, and the `.navs .nav-item .badge` rule documented below would teleport a badge to a
   card corner and paint it red. Same call the internal supply-request tabs made. */
.ef-rtd-kindtabs { margin-bottom: 0.5rem; }
.ef-rtd-kind-count {
  font-weight: 400;
  opacity: 0.75;
  margin-left: 0.25rem;
}
/* THE SELECTED SUB-TAB HAS TO BE OBVIOUS. .ef-subtabs' shared active state is a soft tint from
 * --ef-hover-bg, which on the dark skin is rgba(255,255,255,0.04) -- so on this three-tab strip the
 * chosen one looked barely different from the other two, and the leftmost ("All") read as selected
 * whichever one you had actually picked. Here the active tab gets the accent as TEXT, a solid
 * underline and bold weight, none of which depend on a near-invisible fill; the inactive ones are
 * explicitly muted with a transparent underline so all three keep the same height and nothing shifts
 * when the selection moves. */
.ef-rtd-kindtabs .nav-link {
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--ef-muted-fg, #6b7280);
}
.ef-rtd-kindtabs .nav-link.active,
.ef-rtd-kindtabs.nav-pills .nav-link.active {
  color: var(--ef-accent, var(--bs-primary)) !important;
  background-color: transparent !important;
  border-bottom-color: var(--ef-accent, var(--bs-primary));
  font-weight: 700;
}
.ef-rtd-kindtabs .nav-link.active .ef-rtd-kind-count { opacity: 1; }

/* Drill-down. The expanded pane is a sibling <tr> that spans the board, so its inner table sets its
 * OWN widths rather than inheriting the board's seven fixed columns -- it deliberately does not carry
 * .ef-list-table for that reason. Tinted a shade off the row so an open pane reads as belonging to
 * the row above it rather than as more board. */
.ef-rtd-expand { text-decoration: none; display: inline-flex; align-items: center; max-width: 100%; }
.ef-rtd-chev { transition: transform 0.12s ease-in-out; }
.ef-rtd-chev-open { transform: rotate(90deg); }
.ef-rtd-detail-cell { background-color: var(--ef-stripe-bg, rgba(0, 0, 0, 0.03)); }
.ef-rtd-detail-table { margin-bottom: 0.35rem; }
.ef-rtd-detail-table th:nth-child(2),
.ef-rtd-detail-table th:nth-child(3),
.ef-rtd-detail-table th:nth-child(4) { width: 14%; }
.ef-rtd-detail-total td { font-weight: 700; }
.ef-rtd-detail-note,
.ef-rtd-detail-empty { font-size: 12px; color: var(--ef-muted-fg, #6b7280); }

/* The green "+" on the Add affordances in UCnavOptions-Inventory. Two buttons in that
   one control carried the same inline color; hoisted so there is one definition. */
.ef-nav-add-icon {
  color: darkgreen;
}

/* Read-only "where it is right now" table on the internal request entry forms. Mirrors the
 * queue's On Hand column, so it is output, not an editable location grid. Shared by BOTH
 * members of the internal supply request form group -- InternalSupplyRequestEntry (ef-isre-)
 * and LocationSupplyRequest (ef-lsr-). The pages carry distinct identity classes so selectors
 * can tell them apart; the styling is one rule, not a copy per page. */
.ef-isre-onhand-total,
.ef-lsr-onhand-total {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ef-accent, var(--bs-primary));
}
/* Dlg.Master pins every .form-control to height:38px, which flattens a multiline TextBox
 * into a one-line box. Needs a min-height (not height) so the textarea can still grow.
 * Put this on any TextMode="MultiLine" TextBox instead of an inline height. */
.ef-form-textarea {
  min-height: 130px !important;
  height: auto !important;
}

/* "Marked <status> by <user>" bar on the external supply-request form. It was display:none in
 * that page's own <style> block and nothing ever un-hides it, so it is effectively dormant —
 * kept hidden here rather than dropped, because dropping the rule would make it appear on
 * every request for the first time. Restore it by removing the display:none, not by
 * re-adding a page-level <style>. */
.ef-sre-updatebar {
  display: none;
  text-align: center;
  background-color: yellow;
}

/* Small muted centred note inside a form card ("submit this first, then ..."). */
.ef-form-hint {
  font-size: 0.85rem;
  color: #666;
  text-align: center;
  margin: 8px 0 16px;
}

/* ---- Supply Requests KPI cards + drillable reports (SupplyRequestDashboard.aspx) ----
 * One KPI card sits above each queue card. It reuses the shared .widget treatment, so only
 * the range picker, the tiles, and the two-level report modal are defined here. Colors go
 * through the --ef-* theme vars with the same fallbacks the rest of this file uses, so the
 * cards track the active app theme and still read correctly on the default skin. */

/* The card itself is not a link -- only its tiles are -- so undo .widget's pointer. */
.ef-srk-card {
  cursor: default;
}

/* Range picker: 1D / 5D / 1M / 3M / All as one full-width group, which is what keeps it
   usable at iPhone width -- five equal fifths rather than a wrapping pill row. */
.ef-srk-range .ef-srk-range-opt {
  flex: 1 1 0;
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}
.ef-srk-range-note {
  font-size: 0.75rem;
  margin: 0.35rem 0 0.6rem;
}

/* Tile: a button styled as a stat block. Kept borderless-until-hover so four of them in a
   row read as one panel rather than four boxes. */
.ef-srk-tile {
  display: block;
  width: 100%;
  height: 100%;
  text-align: left;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--ef-menu-border, rgba(0, 0, 0, 0.08));
  border-radius: 0.5rem;
  background-color: transparent;
  color: inherit;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
/* Hover is NEUTRAL on purpose, matching .widget:hover rather than tinting with the accent.
   The accent is reserved on this page for the primary Add action; eight accent-bordered
   tiles read as a wall of blue next to the monochrome queue cards below them. */
.ef-srk-tile:hover,
.ef-srk-tile:focus-visible {
  border-color: var(--ef-card-border, rgba(0, 0, 0, 0.15));
  background-color: var(--ef-hover-bg, rgba(0, 0, 0, 0.04));
}
.ef-srk-tile-label {
  display: block;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ef-muted-fg, #6b7280);
  /* Two lines' worth, always: "Avg fulfilment" wraps in a narrow tile and the others
     don't, and without a floor the big numbers stop lining up across the row. */
  min-height: 2.1em;
  /* Bootstrap's .card sets word-wrap:break-word on everything inside it, so a label in a
     too-narrow tile shed letters onto the next line ("AVG FULFILME/NT", "REQUEST/S").
     Words may wrap, never break; the container query below is what makes them fit. */
  overflow-wrap: normal;
}
/* The tiles go 2-up when the CARD is narrow, not the viewport: with the sidebar open a 13"
   laptop is an xl viewport whose lg-split leaves each card ~400px, where four-up squeezes
   every label into mid-word breaks. Sized on the card body so the same markup is 4-up on a
   wide monitor and 2-up wherever the card itself is tight. */
.ef-srk-card .card-body {
  container-type: inline-size;
}
@container (max-width: 410px) {
  .ef-srk-tile-col {
    width: 50%;
  }
}
/* The stat itself carries WEIGHT, not colour: --ef-heading-fg is the darkest text token,
   so the number reads as the strongest thing in the tile without adding accent. It used to
   be var(--ef-accent), which put eight saturated numbers on a page whose queue cards,
   .widget headers and tables are otherwise all neutral greys. */
.ef-srk-tile-value {
  display: block;
  font-size: 1.4rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ef-heading-fg, var(--ef-body-fg, #516377));
}
/* The Top Item tile holds a name, not a number -- same slot, readable size, and the name
   itself carries .ef-truncate so a long one ellipses instead of blowing out the tile. */
.ef-srk-tile-value-text {
  font-size: 0.95rem;
  line-height: 1.4;
}
.ef-srk-tile-sub {
  display: block;
  font-size: 0.72rem;
  color: var(--ef-muted-fg, #6b7280);
}

/* Report modal. Level 1 is the grouped summary, level 2 the requests behind one group;
   the crumb bar is the only way back, so it stays put at the top of the body. */
.ef-srk-modal-heading {
  min-width: 0;
}
.ef-srk-modal-scope {
  font-size: 0.78rem;
}
.ef-srk-crumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 1.6rem;
  margin-bottom: 0.5rem;
}
.ef-srk-crumb-back {
  text-decoration: none;
  font-size: 0.85rem;
  color: var(--ef-link-fg, var(--ef-accent, var(--bs-primary)));
}
.ef-srk-crumb-current {
  font-weight: 600;
}
/* Summary rows are the drill affordance; they reuse .ef-picker-row for cursor + hover. */
.ef-srk-group-chevron {
  color: var(--ef-muted-fg, #6b7280);
  vertical-align: middle;
}
/* Both report tables inherit .ef-list-table's fixed layout, which would otherwise split
   every column evenly and squeeze the names down to an ellipsis. Give the name column the
   room instead. Counts are the same on both tables regardless of how many summary columns
   a given report has, because the extras are all narrow numbers. */
.ef-srk-summary-table th:first-child {
  width: 55%;
}
/* All eight are pinned (they add to 100%): leaving the tail unset splits the remainder
   evenly and clips the nowrap "37.7d open" in the last column. */
.ef-srk-detail-table th:nth-child(1) { width: 7%; }
.ef-srk-detail-table th:nth-child(2) { width: 25%; }
.ef-srk-detail-table th:nth-child(3) { width: 14%; }
.ef-srk-detail-table th:nth-child(4) { width: 9%; }
.ef-srk-detail-table th:nth-child(5) { width: 11%; }
.ef-srk-detail-table th:nth-child(6) { width: 11%; }
.ef-srk-detail-table th:nth-child(7) { width: 11%; }
.ef-srk-detail-table th:nth-child(8) { width: 12%; }
/* Item + reason stack inside one cell. Below 820px the mobile table-card conversion turns
   the value cell into a flex row, so this wrapper is what keeps the reason UNDER the item
   name instead of beside it (and min-width:0 is what lets .ef-truncate ellipse there). */
.ef-srk-detail-itemwrap {
  display: block;
  flex: 1 1 auto;
  min-width: 0;
}
.ef-srk-detail-reason {
  display: block;
  font-size: 0.75rem;
}
/* In the stacked-card view the value column is only ~40% of a phone screen, so ellipsing
   an item or requester name there hides most of it and there is no hover to reveal the
   title. Let those cells wrap instead -- vertical space is the one thing a card has. */
@media (max-width: 820px) {
  .ef-srk-table .ef-truncate {
    white-space: normal;
    overflow: visible;
    max-width: 100%;
  }
}
.ef-srk-detail-filled {
  font-size: 0.75rem;
}
/* Still-waiting requests: the number is an age, not an outcome, so it is muted. */
.ef-srk-detail-days-open {
  color: var(--ef-muted-fg, #6b7280);
}
.ef-srk-note {
  font-size: 0.78rem;
  margin: 0.75rem 0 0;
}

/* Supply-request link sheet (Admin/SupplyRequestLinks.aspx). Two views off one page: the
 * on-screen table, and the ?p=y print sheet of cut-up QR cards for each site's paper packet.
 * The card sheet itself is styled in assets/css/ef-print-cards.css -- see the note below. */
/* Centred: it is a one-paragraph explanation of the whole page, sitting above a centred card
   title, so a left-aligned block of text under a centred heading read as misaligned. */
.ef-srl-intro { font-size: 13px; max-width: 70ch; margin-left: auto; margin-right: auto; text-align: center; }
/* FOUR columns summing to 100%, and the count is load-bearing: .ef-list-table is
   table-layout:fixed, so a fifth column added without a width here gets none, wraps its header one
   character per line and pushes its content off the card. The Copy column is wide enough for the
   labelled Request + Return pair. */
.ef-srl-table th:nth-child(1) { width: 18%; }
.ef-srl-table th:nth-child(2) { width: 27%; }
.ef-srl-table th:nth-child(3) { width: 35%; }
.ef-srl-table th:nth-child(4) { width: 20%; }
/* The two copy buttons stay on one line and wrap together if the column is squeezed. */
.ef-srl-copywrap {
  display: flex;
  gap: 0.35rem;
  justify-content: flex-end;
  flex-wrap: wrap;
}
/* Centre the card title in the FULL width and take the Print button out of flow, so the heading is
   centred on the card rather than on whatever space the button leaves. */
.ef-srl-header {
  position: relative;
  text-align: center;
}
.ef-srl-title { margin-bottom: 0; }
.ef-srl-header .ef-srl-print {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
}
.ef-srl-url { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; }

/* The print CARD sheet's styling is NOT here: it lives in assets/css/ef-print-cards.css,
 * linked by Admin/SupplyRequestLinks.aspx itself. ?p=y renders under PrintView.Master, which
 * does not load this file at all, so .ef-srl-card rules placed here never reach the printed
 * page. The on-screen rules above (.ef-srl-intro / -table / -url) stay, since that view runs
 * under Site1.Master. */

/* ============================================================================
 * Durable locations model (docs/locations-model-plan.md) -- the Locations /
 * Precincts / Election-setup admin pages, plus the Location picker the storage
 * screens grew. Field hints reuse the muted-foreground token so they track the
 * active theme instead of hard-coding the old inline #6c757d.
 * ============================================================================ */
.ef-sl-location-hint,
.ef-loc-hint {
  margin-top: 5px;
  font-size: 0.85rem;
  color: var(--ef-muted-fg, #6c757d);
}

/* Election Location Setup (Admin/ElectionLocationSetup.aspx). Replaces the 60-line page-local
 * page-local stylesheet that page used to carry, whose rules included bare `table, th, td`
 * selectors and therefore leaked onto anything else the master rendered. Everything here is
 * scoped to .ef-els-*. */
.ef-els-head        { text-align: center; }
.ef-els-title       { margin-bottom: 4px; }
.ef-els-sub         { color: var(--ef-muted-fg, #6c757d); margin-bottom: 0; }
.ef-els-empty       { padding: 1.25rem; }
.ef-els-empty-title { font-size: 1.05rem; margin-bottom: .5rem; }
.ef-els-empty-text  { margin-bottom: 0; }

/* The header sticks under the app navbar so a long list stays readable while scrolling. */
.ef-els-table thead { position: sticky; top: 42px; z-index: 1; }
.ef-els-table th,
.ef-els-table td    { padding: 8px; }
/* One table at a time, full width: the label needs only its own width, the action column is a
   fixed button, and the building name takes the rest. When these two lists sat side by side in
   col-md-5 the same columns could not fit and the tables overflowed into each other. */
.ef-els-th-lbl      { width: 18%; }
.ef-els-th-action,
.ef-els-td-action   { width: 130px; text-align: center; }
.ef-els-tab-count   { font-weight: 400; opacity: 0.75; }

/* Full width, overriding the app-wide `.nav-pills { width: 50% }` at the top of this file.
   That 50% exists because most tabbed pages put TWO strips side by side (destinations left,
   actions right) and together they fill the row; a page with a single strip inherits it and
   renders a half-width rule that stops in the middle of nowhere. */
.ef-els-tabs        { width: 100%; }

/* Excluded rows are painted red. A soft tint rather than the old flat `background-color:red`,
 * which fought every theme and made the label unreadable on the dark skins. */
.ef-els-table tr.excluded > td,
.ef-els-table td.excluded {
  background-color: rgba(220, 53, 69, 0.14);
}
.ef-els-table tr.excluded .ef-els-td-lbl { text-decoration: line-through; }

/* Precinct / EV Site detail (Admin/PrecinctDetail.aspx) -- the "Currently votes at" type-ahead
 * and the add-a-new-place confirm it reveals. The confirm ships with the global .hidden class
 * (display:none!important) and efPctdSyncLocation takes the CLASS off rather than setting a
 * style, so nothing here may set `display` -- it would be overruled while hidden and redundant
 * once shown. */
.ef-pctd-location-new { margin-top: 4px; }
/* The row itself is the shared .ef-toggle-row; only the label's own margin is trimmed, since
 * this one sits under a field rather than in a run of toggles. */
.ef-pctd-lbl-newlocation { margin-bottom: 0; }
/* The typed name the tick would create. Bold already, so only the ellipsis guard is needed --
 * a pasted address can run well past the field. */
.ef-pctd-newlocation-name {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}
.ef-pctd-newlocation-hint { margin-top: 2px; }

/* Storage Locations list (Inventory/StorageLocations.aspx). Column widths are pinned here
 * rather than inline, the same way .ef-srl-table / .ef-picker-table / the .ef-srk-* report
 * tables pin theirs -- the page gained a Location column when the locations model landed and
 * splitting the widths between markup and stylesheet would have made the set unreadable.
 * .ef-list-table supplies table-layout:fixed, which is what makes these widths bind.
 * The below-lg squeeze still comes from .dash-shrink's !important rule in the page. */
.ef-sl-th-location { width: 180px; }
.ef-sl-th-area     { width: 150px; }
.ef-sl-th-position { width: 185px; }
.ef-sl-th-details  { width: 130px; }

/* Pills in the Locations list's Precinct / EV site column (Admin/Locations.aspx), for the rows
 * where nothing votes in the building: Storage (holds stock), Prospective (being researched as an
 * alternate site or EV site) and Retired (was voted in, replaced since). Each stands in for the em
 * dash that cell used to show, so they have to POP -- without weight and a shape they would read as
 * one more grey cell on a row that is anything but idle.
 *
 * `.ef-loc-cell-pill` is the shape, and one tone class carries the meaning. Colour comes entirely
 * from theme tokens, so all three are legible on all ten skins in both light and dark rather than
 * only on the default one -- which rules out a hard-coded amber/grey pair, however natural those
 * would read on the light skin.
 *
 * The tones encode TIME, which is what the three states differ in: solid accent fill = what the
 * building does today; dashed accent outline = provisional, somebody is deciding; muted outline =
 * past tense, deliberately the quietest thing in the column.
 *
 * Deliberately NOT a Bootstrap `.badge`: a bare .badge on a page that also renders a module nav bar
 * is caught by the `.navs .nav-item .badge` bubble rule documented below, which would turn it into
 * a red circle pinned to a card corner. None of them is a link -- the row's Manage button is still
 * the only action. */
/* The Prospective / Retired pills name their precinct or EV site ("Prospective: 41"), so a pill can
 * out-run a column that squeezes to 100px below lg. It ellipsizes ITSELF rather than leaning on the
 * parent .ef-truncate: an inline-block child of that span gets clipped by its overflow:hidden with
 * no ellipsis anywhere, which reads as a pill that was cut off by accident. max-width + nowrap +
 * text-overflow on the pill keeps the shape intact and the truncation deliberate. */
.ef-loc-cell-pill {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 1px 9px;
  border-radius: 10rem;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: 0.02em;
  white-space: nowrap;
  vertical-align: bottom;
}
.ef-loc-storage-pill {
  color: var(--ef-accent, var(--bs-primary));
  background-color: var(--ef-menu-hover-bg, rgba(90, 141, 238, 0.08));
  border: 1px solid var(--ef-accent, var(--bs-primary));
}
.ef-loc-prospect-pill {
  color: var(--ef-accent, var(--bs-primary));
  background-color: transparent;
  border: 1px dashed var(--ef-accent, var(--bs-primary));
}
.ef-loc-retired-pill {
  color: var(--ef-muted-fg, #6b7280);
  background-color: transparent;
  border: 1px solid var(--ef-card-border, #d4d8dd);
}

/* ============================================================================
 * INLINE "VOTES AT" PICKER (Admin/Precincts.aspx + Admin/ElectionLocationSetup.aspx, emitted by
 * BasePage.unitLocationPicker and driven by assets/js/ef-unit-location.js). One markup shape, one
 * stylesheet block, two pages — the point of sharing it is that they cannot drift.
 *
 * The select and the address STACK rather than sitting side by side: an address is long, the column
 * is one of four, and a two-line cell is what keeps both readable without a horizontal scroll.
 * ============================================================================ */
.ef-unitloc {
  display: block;
  max-width: 100%;
}
.ef-unitloc-select {
  max-width: 100%;
  font-size: 0.8rem;
}
.ef-unitloc-address {
  display: block;
  font-size: 11px;
  color: var(--ef-muted-fg, #6b7280);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* "Saved", after an out-of-band save. An ANIMATION rather than a message that stays: the row has
 * already changed in front of you, so the confirmation's job is to be noticed and then get out of
 * the way. Green for saved, the danger token for a failure — a failed save must not look like a
 * successful one, and this is the only feedback there is without a page reload. */
.ef-unitloc-flash {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  margin-left: 0.35rem;
  opacity: 0;
  color: var(--bs-success, #28a745);
}
.ef-unitloc-flash-on {
  animation: efUnitlocFlash 1.8s ease-out 1;
}
.ef-unitloc-flash-bad {
  color: var(--bs-danger, #dc3545);
  animation-duration: 4s;   /* a problem should linger longer than a success */
}
@keyframes efUnitlocFlash {
  0%   { opacity: 0; transform: translateY(3px); }
  12%  { opacity: 1; transform: translateY(0); }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Admin/Precincts.aspx column widths. .ef-list-table is table-layout:fixed, and with nothing
 * pinned its four columns split EVENLY -- a quarter each for a short label, one word of status
 * and two icons, while the "Currently votes at" select (Bootstrap .form-select is width:100%
 * of its cell) truncated building names inside its starved quarter. Pin the three narrow
 * columns and leave the location column unset so it absorbs the remainder -- the same shape
 * .ef-els-table uses (label %, action px, building name takes the rest). Below lg the
 * .ef-dash-shrink squeeze on lbl/status still wins (its !important out-ranks these). */
.ef-pct-th-lbl    { width: 16%; }
.ef-pct-th-status { width: 12%; }
.ef-pct-th-action { width: 130px; }

/* Row-action icons on Admin/Precincts.aspx: manage / split / consolidate / archive in the width one
 * "Manage" button used to take. Sized and spaced to stay tappable (~34px targets) rather than being
 * shrunk to fit, and archive is tinted danger because it is the one with consequences. */
.ef-pct-icon {
  display: inline-block;
  padding: 4px 6px;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--ef-muted-fg, #6b7280);
  text-decoration: none;
}
.ef-pct-icon:hover {
  color: var(--ef-accent, var(--bs-primary));
}
.ef-pct-archive:hover {
  color: var(--bs-danger, #dc3545);
}
.ef-pct-icon-off {
  opacity: 0.35;
  cursor: default;
}

/* Empty-state blurb under a list card that has no rows. Same treatment as .es-empty on the
 * admin-list reference page (Admin/ElectionSetup.aspx) -- centred and generously padded, so an
 * empty list reads as "nothing here yet" rather than a table that failed to render. */
.ef-loc-empty,
.ef-pct-empty {
  text-align: center;
  padding: 30px;
  color: var(--ef-muted-fg, #6c757d);
}

/* ============================================================================
 * Module nav bars (Inventory/userControls/UCnavOptions-Inventory.ascx and
 * -Assets.ascx). Moved here out of those two controls' page-local <style> blocks,
 * which declared `.nav-pills`, `.navs` and `.badge` UNSCOPED -- so any page that
 * included either control restyled EVERY Bootstrap badge and EVERY nav-pills list
 * on it. That is the documented hijack: `.badge` set position:absolute, so the
 * inline label badges on Election Setup, Page Access, UCVendor and Profile were
 * teleported to the corner of whatever box happened to be positioned, painted red
 * and rounded. Scoping to .navs fixes that; the two controls render identically.
 * ============================================================================ */
.navs {
  display: flex;
  -ms-flex-direction: column !important;
  flex-direction: row;
}
/* The two strips are a 50/50 pair: destinations left, actions right-aligned. */
.navs .nav-pills { width: 50%; }
/* Positioning anchor for the count bubble below. */
.navs .nav-item { position: relative; }

/* Count bubble on a nav pill ("3 open requests"). Pulled OUTSIDE the pill's top-right
 * corner at -5px/-5px so it reads as a notification badge overlapping the tab rather
 * than a number tucked inside it. Deliberately a descendant selector rather than a
 * new class: it catches every bare `class="badge"` already in these strips without
 * editing six inline conditionals, and it cannot reach a badge elsewhere on the page. */
.navs .nav-item .badge {
  position: absolute;
  top: -5px;
  right: -5px;
  background: red;
  color: white;
  padding: 2px 6px;
  font-size: 12px;
  border-radius: 50%;
}

/* The Add bar on a list page is the RIGHT half of the 50/50 .navs pair (views left, actions
 * right), so its single link has to be pushed to the far edge -- otherwise Add sits in the
 * middle of the page against nothing. StorageLocations.aspx and Admin/Users.aspx do this with
 * an inline `style="justify-content: end"`; these declare it here instead. */
.ef-loc-addbar,
.ef-pct-addbar,
.ef-rtd-linkbar {
  justify-content: flex-end;
}

/* ============================================================================
 * Admin/TourEditor.aspx -- the internal tool for editing every guided-tour blurb
 * in one place. One collapsible card per tour, collapsed by default because ~160
 * open textareas is unreadable. Styling stays deliberately plain: it is a
 * proofreading surface, not a county-facing page.
 * ============================================================================ */
.ef-te-intro,
.ef-te-notes,
.ef-te-counts { font-size: 13px; max-width: 80ch; }
.ef-te-counts { color: var(--ef-muted-fg, #6b7280); margin-bottom: 0; }

.ef-te-tour-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  cursor: pointer;
  flex-wrap: wrap;
}
.ef-te-tour-key {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-weight: 700;
}
.ef-te-tour-file,
.ef-te-tour-count {
  font-size: 12px;
  color: var(--ef-muted-fg, #6b7280);
}
.ef-te-tour-file { flex: 1 1 auto; }

/* One step: number + flags on a header row, then the title box and the text box. */
.ef-te-step {
  border-top: 1px solid var(--ef-card-border, #e5e7eb);
  padding: 12px 0;
}
.ef-te-step:first-child { border-top: 0; padding-top: 0; }
.ef-te-step-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.ef-te-step-num { font-weight: 600; font-size: 13px; }
.ef-te-step-remove-lbl {
  margin-left: auto;
  font-size: 12px;
  color: var(--ef-muted-fg, #6b7280);
  cursor: pointer;
}
.ef-te-step-title { margin-bottom: 6px; font-weight: 600; }
.ef-te-step-src {
  margin-top: 6px;
  font-size: 12px;
  color: var(--ef-muted-fg, #6b7280);
}
/* A step marked Remove is dimmed rather than hidden, so it stays un-removable. */
.ef-te-step-removed .ef-te-step-title,
.ef-te-step-removed .ef-te-step-text {
  opacity: 0.45;
  text-decoration: line-through;
}

/* ============================================================================
 * Faceted-filter panel -- the right-edge tab + offcanvas of checkbox groups.
 *
 * These declarations are LIFTED VERBATIM from the page-local <style> block in
 * Inventory/userControls/ajaxFilterItems.ascx (the Inventory Dashboard's advanced
 * filter) so any page using them is pixel-identical to it. The control still
 * carries its own copy; fold it onto these next time it is opened rather than
 * copying the block a third time.
 *
 * ONE deliberate difference: the originals declare `h5`, `.section` and `.column`
 * UNSCOPED, so on the Dashboard they restyle every h5 on the page. Here they are
 * scoped under .filterSpace, which is the panel itself -- same result inside it,
 * no leak outside. The icon colour also moved off an inline style attribute.
 *
 * Users: Admin/Locations.aspx.
 * ============================================================================ */
.toggleFilter {
  right: 0px;
  position: fixed;
  z-index: 100;
  font-size: large;
  height: 40px;
  width: 35px;
  background-color: black;
  top: 50%;
  border-radius: 10px 0px 0px 10px;
  cursor: pointer;
}
.toggleFilter .menu-icon { color: #fff; }

.filterSpace {
  width: 100%;
  font-size: small;
}
.filterSpace h5 { text-align: center; }
.filterSpace .section {
  border-radius: 10px;
  padding: 5px 15px 5px 10px;
  margin: 5px;
}
.filterSpace .column { height: 100% !important; }
.filterSpace .cardExtra { margin-bottom: 5px; }
.filterSpace .selector,
.filterSpace .clearFilters { cursor: pointer; }
.filterSpace .clearFilters { color: red; }

/* Election Location Setup card headers: title left, the Include-all action right. */
/* CENTRED heading with "Include all" pinned right, rather than a justify-content-between pair: with
 * the pair the title sat wherever the button's width left it, which read as left-aligned. Same trick
 * as .ef-srl-header and the location banner -- centre the text in the full width and take the button
 * out of flow. Below md the button drops back into flow underneath, where absolute positioning would
 * otherwise overlap a wrapped title. */
.ef-els-cardhead {
  position: relative;
  text-align: center;
  min-height: 2.5rem;
  display: block;
}
.ef-els-cardhead h3 { margin-bottom: 0; }
.ef-els-cardhead .btn {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}
@media (max-width: 767.98px) {
  .ef-els-cardhead .btn {
    position: static;
    transform: none;
    margin-top: 0.5rem;
  }
}

/* A tabbed page with a SINGLE nav-pills strip. The app-wide `.nav-pills { width: 50% }` near
 * the top of this file is right for the usual two-strip bar (destinations left, actions right)
 * where the pair fills the row, but a lone strip inherits it and draws a folder-tab rule that
 * stops halfway across the page. `.navs.pa-tabs` rather than `.pa-tabs` so this beats the
 * `.navs .nav-pills` rule outright instead of relying on which one is declared later. */
.navs.pa-tabs .nav-pills {
  width: 100%;
}

/* Action-card buttons sit alone in a col-md-2, which is genuinely narrow on a laptop or a
 * zoomed browser -- labels like "Save Election", "Request History" or "Request Surplus" ran
 * past the card and got clipped. Let them wrap and scale with the viewport rather than being
 * cut off: clamp keeps them readable at a wide window and shrinks them when the column does.
 * The 2-class selector intentionally outranks .btn-sm's fixed font-size. */
.buttonCard .btn,
.buttonCard input[type="button"],
.buttonCard input[type="submit"] {
  white-space: normal;
  overflow-wrap: break-word;
  font-size: clamp(0.72rem, 0.85vw, 0.95rem);
  line-height: 1.25;
}

/* ============================================================================
 * Dropdown-list editor (EditDDl.aspx) -- the app-wide editor for any <select>
 * whose options live in the DropDownList table. Replaces the 16-line page-local
 * <style> block it used to carry, whose .ddl-* rules hard-coded #f0f0f0 /
 * #fafafa / #c00 and so ignored the active theme entirely. Everything here is
 * scoped to .ef-ddl-*.
 * ============================================================================ */

/* The DDName, shown next to the heading: it is a control id, so it reads as code. */
.ef-ddl-name {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.8rem;
  font-weight: 400;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--ef-stripe-bg, rgba(0, 0, 0, 0.05));
  color: var(--ef-muted-fg, #6c757d);
}

/* ONE OPTION = ONE CARD, on one grid template shared by the option cards, the
 * add card and the archived cards -- so every box starts and ends on the same
 * line all the way down. The options are a UL/LI list, not a .table.dataTable:
 * that class pairing pulls in the grid control's styling (row banding, cell
 * padding, and the global below-820px table-to-cards conversion), all of which
 * fights a row that is a form field with a drag handle beside it.
 *
 * handle | the option text, full width | one action. There is deliberately no
 * label and no column header: a single field on a card under a heading that
 * already says "Options" needs neither. */
.ef-ddl-item {
  display: grid;
  /* The action track is FIXED, not auto: auto sizes to its own button, so the
   * Archive cards and the Add card ended their text boxes on different lines. */
  grid-template-columns: 26px minmax(0, 1fr) 84px;
  gap: 10px;
  align-items: center;
}

/* The card itself. Not the app's `.card` class: that carries the detail-page
 * card's own padding/margin and would read as a card nested in a card. Same
 * theme tokens, so it tracks the active skin either way. */
.ef-ddl-card {
  padding: 8px 10px;
  margin-bottom: 8px;
  border: 1px solid var(--ef-card-border, rgba(0, 0, 0, 0.1));
  border-radius: 8px;
  background: var(--ef-card-bg, #fff);
}
.ef-ddl-card:hover { border-color: var(--ef-accent, var(--bs-primary)); }

/* The list is a plain UL stripped of bullets and indent -- the cards do the
 * separating, so it has no rules or spacing of its own. */
.ef-ddl-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The one field, filling the whole middle track. min-width:0 is what actually
 * lets it shrink inside the grid rather than pushing the card wider than the
 * dialog. */
.ef-ddl-cell-value { min-width: 0; }
.ef-ddl-cell-value .form-control { width: 100%; }

/* The drag handle IS the drag affordance -- the card itself is not draggable, so
 * only this element gets the grab cursor. */
.ef-ddl-handle {
  cursor: grab;
  font-size: 1.15rem;
  color: var(--ef-muted-fg, #6c757d);
}
.ef-ddl-handle:active  { cursor: grabbing; }
.ef-ddl-item:hover .ef-ddl-handle { color: var(--ef-accent, var(--bs-primary)); }

/* Full width of the fixed action track, and never wrapped: "Archive" and
 * "Restore" both fit on one line, and the .buttonCard rule that lets action-card
 * labels wrap does not reach in here. */
.ef-ddl-cell-action { text-align: center; }
.ef-ddl-cell-action .btn {
  width: 100%;
  padding-left: 6px;
  padding-right: 6px;
  white-space: nowrap;
}

/* The card being dragged. Kept subtle: the list reorders live underneath the
 * cursor, so the card only has to stay identifiable, not shout. */
.ef-ddl-dragging {
  opacity: 0.55;
  outline: 1px dashed var(--ef-accent, var(--bs-primary));
}

/* The add-an-option card. Outside the sortable UL (so it can never be dragged
 * into the ordering) but on the same grid, tinted so it reads as a form rather
 * than as another existing option. */
.ef-ddl-newitem {
  margin-top: 10px;
  background: var(--ef-stripe-bg, rgba(0, 0, 0, 0.03));
}
.ef-ddl-newicon        { font-size: 1.15rem; color: var(--ef-accent, var(--bs-primary)); }

/* Archived cards: no drag column (nothing to position) and read-only text in
 * place of the box -- restore it to edit it. The strike-through means a scan of
 * the list reads as "retired" without anything having to say so. */
.ef-ddl-architem       { grid-template-columns: minmax(0, 1fr) 84px; }
.ef-ddl-arch-value {
  color: var(--ef-muted-fg, #6c757d);
  text-decoration: line-through;
  padding: 6px 0;
}

/* NO stacking breakpoint, deliberately. With one box per card the fixed parts add
 * up to ~130px, so minmax(0, 1fr) leaves a usable field at any width this page is
 * ever opened at -- and it is normally opened in the stock ~500px Bootstrap modal,
 * which any viewport-based "phone" breakpoint would misread as a phone and stack.
 * That is exactly the bug the two-field version had. */

.ef-ddl-intro-icon     { vertical-align: text-bottom; }
.ef-ddl-empty          { padding: 8px 0; font-style: italic; }


/* ------------------------------------------------------------------ Pallet Manager archive plan
 * The card that opens under the contents table when Archive is clicked: one row per item, any
 * number of destination lines, plus a Consumed box.
 *
 * Each destination is a bordered block carrying its OWN quantity, and there is no separate Qty
 * column. Two earlier shapes failed: the quantity beside the picker in a flex row collapsed the
 * input to ~20px and shoved the remove control under the Consumed header, and a separate Qty
 * column had to stay in index step with picker blocks that change height the moment one shows a
 * crumb -- so the columns drifted apart exactly when a row had several destinations.
 *
 * The Unassigned cell is the whole point of the card, so it states its own state: red until the
 * row balances, muted once it does. Colour is NOT the only signal -- the number itself reads 0
 * when the row is done, and Confirm stays disabled -- so this is reinforcement, not the sole cue. */
/* FULL WIDTH, NO SCROLLBAR, and NO COLUMN WIDTHS AT ALL -- the table scales itself inside the
 * card. Every width this section used to carry has been removed, and that is deliberate: each
 * attempt to state them was a separate bug.
 *
 *   - Percentages under .ef-list-table's table-layout:fixed became absolute shares that ignored
 *     min-content, which broke every heading mid-word ("ON HA / ND", "CONSU / MED") and wrapped a
 *     three-digit balance to "10 / 0".
 *   - Replacing them with min-width floors summed past the card width, so the wrapper scrolled and
 *     the operator had to drag the table sideways to read a number.
 *
 * What is left is the only part that was ever load-bearing: auto layout, so min-content is
 * honoured and a nowrap heading can never break; width:100%, so the table fills the card; and
 * nothing anywhere setting an unbounded minimum. The browser distributes the space, which is what
 * "scale within its space" means.
 *
 * The one rule to keep in mind when adding a column: it must not contain anything whose min-content
 * is unbounded. That is why the item name wraps instead of carrying .ef-truncate (a nowrap name
 * makes the column's minimum the whole name) and why the wrapper's inherited 760px floor is
 * cancelled below. Either one alone was enough to overflow an ~840px card. */
.ef-pmarc-table           { table-layout: auto; width: 100%; }
.ef-pmarc-table th,
.ef-pmarc-table td        { vertical-align: top; }

/* Every heading on one line. With auto layout this is what sets each column's true minimum, so no
 * amount of content elsewhere can squeeze a heading into wrapping. */
.ef-pmarc-table th        { white-space: nowrap; }

/* Quantities never break across lines either -- a wrapped "100" reads as two numbers. */
.ef-pmarc-td-onhand,
.ef-pmarc-td-consumed,
.ef-pmarc-td-left         { white-space: nowrap; }

/* Wraps on purpose (see the item cell's comment in the markup); breaks a long single token rather
 * than widening the column. */
.ef-pmarc-name            { overflow-wrap: anywhere; }

/* One destination line. position:relative so the clear control can sit in its own top-right
 * corner instead of in the flow, where it landed between the two inputs. */
.ef-pmarc-alloc {
  position: relative;
  padding: 6px 22px 6px 8px;
  margin-bottom: 6px;
  border: 1px solid var(--ef-border, #e4e6e8);
  border-radius: 4px;
}
.ef-pmarc-drop {
  position: absolute;
  top: 2px;
  right: 4px;
  color: var(--bs-danger, #dc3545);
  text-decoration: none;
  font-size: 1.05rem;
  line-height: 1.2;
}
.ef-pmarc-drop:hover      { color: var(--bs-danger, #dc3545); opacity: .75; }

/* The walk so far. Small and muted: it is context, and the dropdown under it is the control. */
.ef-pmarc-crumb           { font-size: .8rem; line-height: 1.35; margin-bottom: 2px; }
.ef-pmarc-crumb:empty     { display: none; }
.ef-pmarc-crumb-path      { color: var(--ef-muted-fg, #6c757d); }
.ef-pmarc-change          { font-size: .78rem; text-decoration: none; white-space: nowrap; }
.ef-pmarc-loc             { width: 100%; }

/* The quantity sits under its own picker, labelled, so a row with three destinations reads as
 * three "there, this many" pairs rather than two columns the eye has to pair up. */
.ef-pmarc-qtyrow          { display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.ef-pmarc-qtylbl {
  font-size: .78rem;
  color: var(--ef-muted-fg, #6c757d);
  margin: 0;
  white-space: nowrap;
}
/* 90px minus the number spinner clipped the second digit of a two-digit value ("2(" for 20). */
.ef-pmarc-qty             { width: 100px; }
.ef-pmarc-consumed        { width: 100px; margin-left: auto; }

.ef-pmarc-left            { font-weight: 600; }
.ef-pmarc-bad             { color: var(--bs-danger, #dc3545); }
.ef-pmarc-good            { color: var(--ef-muted-fg, #6c757d); font-weight: 400; }

.ef-pmarc-add             { white-space: nowrap; text-decoration: none; font-size: .85rem; }
.ef-pmarc-cancel          { font-size: .85rem; }
.ef-pmarc-summary:empty   { display: none; }

/* Below the global table-to-cards breakpoint each value cell becomes a flex row: the headings are
 * labels beside their values rather than a header row, so they may wrap, and the right-aligned
 * inputs go back to the normal flow. */
@media (max-width: 820px) {
  .ef-pmarc-table th,
  .ef-pmarc-table td      { white-space: normal; }
  .ef-pmarc-consumed      { margin-left: 0; }
}

/* CANCEL the floor, do not raise it. This table inherits .ef-list-table's
 * `.ef-req-scroll > .ef-list-table { min-width: 760px }`, and that alone overflowed the ~840px
 * card once cell padding was counted -- the scrollbar it produced was the whole complaint. Equal
 * specificity, so being later in the file is what makes this win. The .ef-req-scroll wrapper stays
 * in the markup as a containment guard: if some future column does overflow, it scrolls INSIDE the
 * card rather than making the page scroll sideways. In practice nothing reaches it. */
.ef-req-scroll > .ef-pmarc-table { min-width: 0; }


/* ------------------------------------------------------- Transaction history (UCstorageLocation)
 * TWO ROWS PER TRANSACTION, both surfaces. Type used to BE the note, so the column was full of
 * sentences that also repeated the Location beside it ("Position archived -- moved to Loading Dock
 * D1" next to "Storage Room S2"). Type is now derived from the ledger and the note demoted to a
 * reason -- but that made five columns, and five columns do not fit the inline list's card (the
 * narrow column of an item page): the headings themselves broke mid-word and the table overflowed.
 *
 * So the pair. `.ef-txn-r1` carries WHAT happened under three headings -- type, movement, change --
 * and `.ef-txn-r2` spans all three with WHY and WHEN. The second line needs no headings because a
 * reason and a timestamp say what they are, and dropping to three columns leaves the movement
 * enough width to read.
 *
 * The modal uses the identical shape even though it has room for five: one template to maintain,
 * one thing for the operator to learn, and no width at which a column can overflow. */
.ef-txn-table             { table-layout: auto; width: 100%; }
.ef-txn-table th          { white-space: nowrap; }
.ef-txn-th-change         { white-space: nowrap; }
.ef-txn-change            { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ef-txn-move              { overflow-wrap: anywhere; }

/* NO RULE INSIDE A PAIR. Bootstrap puts a border-bottom on every cell, so the two rows of one
 * transaction had a line between them -- which read as a boundary between records and made the
 * reason look like it belonged to the transaction below. Killing r1's bottom border leaves r2's as
 * the only rule, so the line the eye sees is the one that actually separates transactions. */
.ef-txn-pairs .ef-txn-r1 > td {
  border-bottom: 0;
  padding-bottom: 2px;
}
.ef-txn-pairs .ef-txn-r2 > td {
  border-top: 0;
  padding-top: 0;
  padding-bottom: 10px;
}

/* Reason hard left, timestamp hard right, both x-small and muted -- the second line is context
 * for the row above it, not a peer of it.
 *
 * The alignment is a flex wrapper INSIDE the cell, not text-align on the cell: the cell holds
 * both halves and only the timestamp moves. Flex on the <td> itself would take it out of table
 * layout and lose the colspan. */
.ef-txn-r2 > td           { line-height: 1.4; }
.ef-txn-r2-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: x-small;
}
.ef-txn-when              { white-space: nowrap; }
.ef-txn-reason,
.ef-txn-when              { color: var(--ef-muted-fg, #6c757d); }

/* Direction reads from the sign, so the sign is what gets the colour -- not the row, which would
 * make an eight-row history a stripe of red. */
.ef-txn-out               { color: var(--bs-danger, #dc3545); }
.ef-txn-in                { color: var(--bs-success, #198754); }

/* Type is a short verb now, so it can carry weight without shouting. */
.ef-txn-type              { font-weight: 600; }
