/* =============================================================================
 * mobile.css — responsive / small-screen layer for ShapeDo
 * -----------------------------------------------------------------------------
 * This is the single home for mobile UI/UX rules. Do NOT scatter mobile tweaks
 * into style.css / style-rtl.css — add them here so they are easy to find and
 * review, and so desktop stays unaffected (every rule lives inside a breakpoint).
 *
 * Loaded AFTER style.css and style-rtl.css in every layout
 * (layout.phtml, basic-with-header.phtml, basic.phtml, basic-with-header-js.phtml)
 * so these rules win the cascade.
 *
 * The app is RTL (Hebrew) by default — keep rules direction-aware. Mobile is
 * detected at runtime via user-agent ($scope.isMobile); these CSS rules are
 * width-based so they also respond to rotation/resize.
 *
 * Breakpoints:
 *   - phone / small tablet : max-width 768px
 *   - small phone          : max-width 480px
 *
 * See docs/MOBILE-UI.md for the rated backlog this file implements. Each item
 * gets its own clearly-marked section below as it is approved & built.
 * ========================================================================== */

/* ---------------------------------------------------------------------------
 * Phone / small tablet (≤ 768px)
 * ------------------------------------------------------------------------- */
@media only screen and (max-width: 768px) {

    /* -----------------------------------------------------------------------
     * Edge-to-edge content: use the full webview width on phones. The mobile
     * shell DOM is body > #wrap > .container#main-container > [ui-view] >
     * .row > #main-content.col-xs-12 > #content-view. The layout .row's -10px
     * side margins already cancel #main-container's 10px padding (so
     * #main-content sits flush at x=0); the visible gutter is therefore just:
     *   #main-content  side padding (~15px, the Bootstrap column)
     *   #content-view  padding 20px + 1px border + 40px bottom margin (the card)
     * Zeroing the column padding is overflow-safe (the row already accounts for
     * it) and flattening #content-view removes the card inset. We do NOT touch
     * #main-container / .row — that would unbalance the grid and overflow.
     * --------------------------------------------------------------------- */
    #main-content {
        padding-left: 0;
        padding-right: 0;
    }
    #content-view {
        padding: 8px;        /* small breathing room, was 20px */
        border: 0;           /* drop the card border */
        margin-bottom: 0;    /* was 40px */
    }

    /* -----------------------------------------------------------------------
     * #6 — Board compare-strip: denser mobile layout. Smaller thumbnails so
     * THREE versions fit per row (the mobile cap is raised 2->3 in
     * board-thumb-row.html), and tighter rows so more files fit on screen.
     *
     * Scoped with `.isMobile` (set on the version <span> by board-thumb-row.html
     * when $scope.isMobile is true) so these only affect the mobile board
     * layout — matching the existing `.isMobile` board rules in style.css.
     * Defaults being overridden: thumb 80×80, version height 100px,
     * thumb-bar 80px, compare .btn min-width 74px.
     * --------------------------------------------------------------------- */

    /* Smaller thumbnails (80 -> 64) so 3 versions + compare controls fit a phone row */
    .execution-board-table .isMobile .board-thumb {
        height: 64px;
        width: 64px;
    }
    .execution-board-table .isMobile .board-thumb-bar {
        height: 66px;
    }
    /* Tighter rows so more files fit vertically (100 -> 86) */
    .execution-board-table .isMobile .board-version {
        height: 86px;
        margin-bottom: 6px;
    }

    /* The "View" (צפה) tap overlay must match the resized 64px thumbnail — the
       default .isMobile size is 82px (for the old 80px thumb), which left it
       18px oversized so the button sat ~9px off-centre. Flex-centre the button. */
    .execution-board-table .isMobile .board-view-btn {
        height: 64px;
        width: 64px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .execution-board-table .isMobile .board-view-btn:hover {
        padding: 0;
    }

    /* Compact compare control: narrow enough for 2 to sit between 3 thumbs,
       but still a usable ~36px-tall tap target, vertically centred */
    .execution-board-table .isMobile .board-version.board-compare-arrows .btn,
    .execution-board-table .isMobile .board-version.board-compare-arrows button,
    .execution-board-table .isMobile .board-version .compare-btn {
        min-width: 0;
        min-height: 0;
        padding: 3px 8px;
        font-size: 11px;
        line-height: 1.4;
        margin: 24px 3px 6px 3px;
    }
    /* Re-centre the directional arrow against the shorter thumbnails */
    .execution-board-table .isMobile .board-version .board-arrow {
        margin-top: 50px;
        margin-left: 6px;
        margin-right: 6px;
        font-size: 18px;
    }

    /* "Show more revisions" expand arrow: compact but tappable */
    .execution-board-table .isMobile .expand-revision {
        min-height: 36px;
        min-width: 36px;
        margin-top: 34px;
        margin-left: 6px;
        margin-right: 6px;
    }

    /* -----------------------------------------------------------------------
     * #4 — File-row actions: the inline icons (delete/edit/move/merge/share/
     * pin/…) are opacity:0.3 + hover-only, so unusable on touch. On mobile
     * they're collapsed into a single ⋯ overflow menu (board-thumb-row.html).
     * The row header is a flex row [ filename | ⋯ ] so the kebab stays pinned
     * to the trailing edge and long filenames wrap instead of pushing it down.
     * --------------------------------------------------------------------- */
    .execution-board-table .board-row-header {
        display: flex;
        align-items: flex-start;
        gap: 8px;
    }
    /* Filename takes the remaining width and wraps (even unbroken strings) */
    .execution-board-table .board-row-header .board-row-title {
        flex: 1 1 auto;
        min-width: 0;
        overflow-wrap: anywhere;
    }
    /* ⋯ stays put, top-aligned with the first line of the filename */
    .execution-board-table .board-row-header .board-row-actions {
        flex: 0 0 auto;
        float: none;
    }
    .execution-board-table .board-row-actions-toggle {
        opacity: 1;
        min-width: 36px;
        min-height: 36px;
        padding: 6px 10px;
        font-size: 14px;
        line-height: 1;
    }

    /* Tidy the file-row header: checkbox + PDF badge + filename flow together on
       one line (filename wraps inline instead of dropping below the badge), with
       the sheet/plan name as a muted subtitle on its own line. */
    .execution-board-table .board-row-title label {
        font-weight: 600;
        margin-bottom: 0;
        line-height: 1.35;
    }
    .execution-board-table .board-row-title .board-row-name {
        /* !important beats the element's inline style="display:inline-block",
           which otherwise drops the whole filename below the checkbox + badge */
        display: inline !important;
        font-weight: 600;
    }
    .execution-board-table .board-row-title .board-row-subtitle {
        display: block;
        margin-top: 2px;
        font-size: 12px;
        font-weight: 400;
        color: #888;
    }
    .execution-board-table .board-row-title .board-row-subtitle-sep {
        display: none;   /* drop the leading "|" before the sheet name on mobile */
    }
    .execution-board-table .board-row-title input[type="checkbox"] {
        transform: scale(1.3);   /* roomier tap target */
        margin-inline-start: 3px;
        vertical-align: middle;
    }
    .execution-board-table .board-row-title .label {
        vertical-align: middle;
    }
    /* Filetype shown as a small icon (reuses the <file-icon> directive) instead
       of the boxed badge — lighter, and scales to xlsx/doc/etc. */
    .execution-board-table .board-row-title .board-row-type-icon {
        display: inline-block;
        vertical-align: middle;
        margin-inline-end: 6px;
    }
    .execution-board-table .board-row-title .board-row-type-icon img {
        height: 18px;
        width: auto;
        vertical-align: middle;
    }

    /* -----------------------------------------------------------------------
     * Folder rows: the grid folder icon is 80px tall + 20px padding (~120px)
     * with a 22px name — far too tall on a phone. Shrink the icon, name and
     * row height, and re-anchor the overlay markers + action menu to match.
     * --------------------------------------------------------------------- */
    .execution-board-table .execution-folder img {
        height: 38px;
        padding: 4px;
    }
    /* caption line-box MUST equal the icon box height (38px) so the name and the
       folder icon share a vertical centre — otherwise they top-align at different
       heights and read as misaligned */
    .execution-board-table .execution-folder .caption {
        line-height: 38px;
        margin-inline-start: 12px;   /* breathing room between the name and the icon */
    }
    .execution-board-table .execution-folder .caption .name {
        font-size: 14px !important;   /* beats the inline style="font-size:22px" */
    }
    /* overlay markers (parent-folder level-up arrow, empty-folder ✕) re-anchored
       over the smaller icon */
    .execution-board-table .execution-folder i {
        top: 9px;
        left: 12px;
        font-size: 10px;
    }
    .execution-board-table .execution-folder i.empty-folder-icon {
        top: 9px !important;
        left: 12px !important;
    }
    /* the ⋮ action menu wrapper hard-codes margin-top:20px inline; 3px centres the
       32px-tall toggle against the 38px folder icon/name (centre ~td_top+21.5) */
    .execution-board-table .board-folder > .pull-left,
    .execution-board-table .board-folder > .pull-right {
        margin-top: 3px !important;
    }

    /* -----------------------------------------------------------------------
     * Board toolbar (#5): the action buttons (New File/Folder, Compares, view
     * toggle, files menu) float and wrap unevenly; the search floats too. On
     * mobile, stack the header sections full-width and lay the buttons out as a
     * tidy wrapping flex row with real tap targets. (Containers identified via
     * :has() — the search one holds #custom-search-input.)
     * --------------------------------------------------------------------- */
    /* stack header sections in a deliberate order: breadcrumb, search, actions */
    #content-header {
        display: flex;
        flex-direction: column;
    }
    #content-header > #path {
        order: 0;
        margin-bottom: 8px;
    }
    #content-header #content-buttons:has(#custom-search-input) {
        order: 1;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
    }
    #content-header #content-buttons:not(:has(#custom-search-input)) {
        order: 2;
    }
    #content-header #content-buttons {
        float: none !important;
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 0 8px 0 !important;
        padding: 0 !important;
    }
    /* search input grows to fill the row; Filters + Actions sit beside it */
    #content-header #custom-search-input {
        float: none !important;
        flex: 1 1 120px;
        min-width: 0;
        width: auto !important;
        margin: 0 !important;
        padding: 0 !important;
    }
    /* action-buttons container (the one WITHOUT the search box) */
    #content-header #content-buttons:not(:has(#custom-search-input)) {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
    }
    #content-header #content-buttons:not(:has(#custom-search-input)) > * {
        float: none !important;
        margin: 0 !important;
    }
    #content-header #content-buttons .btn {
        min-height: 38px;
        display: inline-flex;
        align-items: center;
        gap: 5px;
    }

    /* Filters button (was hidden-xs/sm): auto-width, on the search row */
    #content-header .filtersAction {
        float: none !important;
        flex: 0 0 auto;
        width: auto !important;
        margin: 0 !important;
        padding: 0 !important;
    }
    /* Wrap the search input-group as one bordered box so the magnifier button
       (a separate input-group cell) sits INSIDE the field instead of floating
       outside its border. */
    #content-header #custom-search-input .input-group {
        border: 1px solid #ccc;
        border-radius: 4px;
        background: #fff;
        overflow: hidden;
    }
    #content-header #custom-search-input tags-input,
    #content-header #custom-search-input tags-input .tags {
        border: none !important;
        box-shadow: none !important;
        background: transparent !important;
    }
    /* Magnifier button nudge: position:relative, so RTL (Hebrew/mobile) resolves
       to `right`, while LTR (English) keeps its `left`. */
    #content-header #custom-search-input button {
        right: -8px;
    }
    #content-header .filtersAction .btn {
        height: 40px !important;   /* overrides inline height:41px */
        min-height: 40px;
    }
    /* icon-only Filters button on mobile (drops the "Filters" label) */
    #content-header .filtersAction .filters-label {
        display: none;
    }
    /* advanced filter panel wraps to its own full-width row below the search row,
       and lays each filter out as one row: inline [label] [control] */
    #content-header .advanced-search {
        flex: 1 1 100%;
        display: block;
    }
    #content-header .advanced-search br {
        display: none;
    }
    #content-header .advanced-search.active {
        max-height: none;
        overflow: visible;
    }
    /* each filter on its own row: inline [label] [control] */
    #content-header .advanced-search .filter-row {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-top: 10px;
    }
    #content-header .advanced-search .filter-row .datepicker-label {
        flex: 0 0 auto;
        margin: 0 !important;
        white-space: nowrap;
    }
    #content-header .advanced-search .filter-row .filter-control {
        flex: 1 1 auto;
        min-width: 0;
        margin: 0 !important;
    }
    /* date controls only need to fit a dd/MM/yy value + calendar button — don't
       let them stretch the full row width. Size the input itself and let the
       control/group shrink to fit (the date-picker nests the input in an inner
       div, so capping the outer control just makes that inner flex overflow). */
    #content-header .advanced-search .filter-row .filter-control:has(.input-group) {
        flex: 0 0 auto;
        width: auto;
    }
    #content-header .advanced-search .filter-row .filter-control .input-group {
        width: auto !important;
    }
    #content-header .advanced-search .filter-row .filter-control .input-group input.form-control {
        width: 110px !important;
        flex: 0 0 auto;
    }
    /* selects (Search in / Type / custom lists) → full-width blocks.
       font-size:16px stops iOS Safari from zooming the page when the control is
       focused/opened (the "shows on top with weird fonts" effect) and gives them a
       regular, touch-sized look. */
    #content-header .advanced-search select {
        width: 100% !important;
        max-width: 100% !important;
        display: block !important;
        float: none !important;
        font-size: 16px !important;
        height: 40px !important;
    }
    /* same anti-zoom treatment for the date inputs; match the 40px control height
       so the input and the calendar button are the same height */
    #content-header .advanced-search .input-group .form-control {
        font-size: 16px !important;
        height: 40px !important;
    }
    #content-header .advanced-search .input-group .input-group-btn button {
        height: 40px !important;
    }
    #content-header .advanced-search .filter-control .input-group {
        align-items: stretch;
    }
    /* The uib-datepicker calendar popup is absolutely positioned inside a 0×0
       wrapper, so on mobile it rendered off the right edge of the viewport. Pin it
       to the viewport so the whole calendar is visible. */
    .advanced-search .uib-datepicker-popup.dropdown-menu {
        position: fixed !important;
        left: 8px !important;
        right: 8px !important;
        top: 50% !important;            /* override uib's inline top (it set -9999) */
        bottom: auto !important;
        transform: translateY(-50%) !important;
        width: auto !important;
        max-width: none !important;
        overflow-x: auto !important;
        z-index: 1060 !important;
        direction: rtl;                 /* RTL day grid */
    }
    /* centre the month/year title across its header cell */
    .advanced-search .uib-datepicker-popup .uib-title {
        width: 100%;
        text-align: center;
    }
    /* date pickers render as a Bootstrap .input-group (icon button + input) —
       make the group fill the row and let the input flex to fill it */
    #content-header .advanced-search .input-group {
        width: 100% !important;
        display: flex !important;
    }
    #content-header .advanced-search .input-group .form-control {
        flex: 1 1 auto;
        width: auto !important;
    }

    /* All toolbar actions collapsed into one full-width Actions menu (board.html
       renders this only on mobile; the desktop button row is ng-if="!isMobile") */
    #content-header .mobile-board-actions {
        flex: 0 0 auto;
        margin: 0;
    }
    #content-header .mobile-board-actions > .btn {
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
    }
    #content-header .mobile-board-actions .dropdown-menu {
        width: 100%;
    }
    #content-header .mobile-board-actions .dropdown-menu > li > a {
        padding: 10px 14px;
        font-size: 14px;
    }
    #content-header .mobile-board-actions .dropdown-menu > li > a > i.fa-fw {
        margin-inline-end: 8px;
    }

    /* Form view (#form2): lay the mobile Actions menu + Activity Log button as a
       tidy row instead of the floated btn-xs pile-up. Override the pull-left/right
       float the ng-class still applies. */
    #form-content #content-header .form-header-actions-mobile {
        float: none !important;
        display: flex;
        gap: 8px;
        margin-top: 10px;
        flex-wrap: wrap;
    }
    #form-content #content-header .form-header-actions-mobile .btn {
        margin: 0;
    }

    /* Form report table (#form2): the ~45 per-form-type report templates
       (public/directives/*.html) all share the same skeleton —
       `.report-wrapper > table.table-bordered` with `table-layout:fixed` and a
       6-column grid (full-width rows use colspan="6", the meta strip uses
       colspan="1" cells). At phone width the fixed ~64px columns push content
       out of its cell — the submission date overflows, labels wrap to 3 lines.
       Relax to content-sizing so each column takes the room it needs, and add a
       horizontal-scroll safety net so a wide row never overflows the page.
       Generic: scoped to `.report-wrapper table`, so it covers every form type. */
    .report-wrapper {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* Bootstrap `.row` carries negative horizontal margins (this project: 0 -10px,
       see style.css) that must be absorbed by a padded `.container`/`.col` ancestor.
       Embedded report blocks (e.g. <report-images-box> → report-images-row.html)
       drop `.row`s straight into `.report-wrapper`, which has no such padding — so
       each row spills ~10px past the edge and, combined with the overflow-x:auto
       above, renders a small horizontal scrollbar on phones (the document itself
       does not scroll). Neutralize the outdent on mobile; below `md` every column
       is full-width/stacked, so the gutter is not needed. */
    .report-wrapper .row {
        margin-left: 0;
        margin-right: 0;
    }
    /* Same Bootstrap `.row` negative-margin overflow, but one level up: the form
       view wraps its content in `#form-content > .row` (margin 0 -10px) whose parent
       `#form-content` has no compensating padding, so it spills ~10px and shows a
       ~2px scrollbar on the `#content-view` scroll container. Neutralize on mobile
       (columns are full-width/stacked below `md`). */
    #form-content > .row {
        margin-left: 0;
        margin-right: 0;
    }
    /* descendant (not `>`) — many templates wrap the table a few levels deep */
    .report-wrapper table.table-bordered {
        /* the templates set `style="table-layout: fixed"` inline — beat it */
        table-layout: auto !important;
    }
    /* EXCEPTION: a report table that embeds a form-table **card**
       (`.form-table-wrap`, e.g. change-order / site-log items). Under the
       `table-layout:auto` above, the outer table sizes to content, so when a card
       is expanded its min-content (~viewport width) inflates the outer table past
       `.report-wrapper` → a horizontal scrollbar that appears only when a card is
       opened. Keep such tables at their intended fixed layout so the card fits
       instead of stretching the table. (`:has` is supported by all current mobile
       browsers.) */
    .report-wrapper table.table-bordered:has(.form-table-wrap) {
        table-layout: fixed !important;
        width: 100%;
    }
    /* site-log "3-up" section: a report table whose single data row holds SEVERAL
       form-table cards side by side (כח אדם / חומרים / ציוד = data.manpower /
       recieved_materials / equipment), with a matching header row of `<th>` labels
       above. On a phone the 3 columns are far too narrow. Reflow to one column and
       interleave each header with its card. Detected by "a 2nd data cell also holds
       a card" so single-card tables (change-order, above) are unaffected.
       `<tr>` → display:contents promotes the th/td into a 1-col grid on `<tbody>`;
       `order` pairs th(n) immediately above td(n). Grid (not flex) is required — a
       column flex-box collapsed the card cells to ~20px. All 3-up templates have
       exactly 3 columns (verified across the site-log-* set). */
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) {
        display: block;
        width: 100%;
    }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody {
        display: grid;
        grid-template-columns: 1fr;
    }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr {
        display: contents;
    }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > th,
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > td {
        display: block;
        width: auto !important;
        height: auto !important;
        border: 0;
    }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > th:nth-of-type(1) { order: 1; }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > td:nth-of-type(1) { order: 2; }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > th:nth-of-type(2) { order: 3; }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > td:nth-of-type(2) { order: 4; }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > th:nth-of-type(3) { order: 5; }
    .report-wrapper table.table-bordered:has(> tbody > tr > td:nth-of-type(2) .form-table-wrap) > tbody > tr > td:nth-of-type(3) { order: 6; }
    /* keep the narrow meta labels (Application date / Schedule number / From …)
       on one line instead of wrapping tall; auto layout gives them the width */
    .report-wrapper table.table-bordered tr.text-center > td:not([colspan]) {
        white-space: nowrap;
    }
    /* ---- Form HEADER table reflow (mobile) — applied to ALL form templates ----
       Scope = the main form table, identified by the logo <img> (`:has(img[ng-src])`).
       Every form has exactly one such table; nested tables (the items card, totals) carry
       no logo and are untouched — so this reflows both the standalone header tables
       (site-log, rfi, ncr, …) AND the all-in-one tables (the change-order family, whose
       one big table also embeds the items card + totals — verified those render fine as
       full-width grid cells below the reflowed header). On a phone these headers overflow
       (the datepicker column alone is ~157px) → horizontal scroll with the last RTL column
       (e.g. קבלן) off-screen, and meta values (e.g. "Admin User") clipped.
       Reflow to a 2-col "label : input" grid: any multi-column cell (logo, title,
       description, every colspan field row, and the items/totals cells) spans full width;
       the plain label/value cells pair up. `order` interleaves each label (col 1) with its
       input (col 2) — the label lives in the row carrying the rowspan title, its input in
       the next row. The families share this logo + rowspan-title + label-row/input-row +
       trailing colspan-rows structure, so one rule set covers them.
       Robust to field count (extra order rules just no-op), to headers with no rowspan
       (impeding-event → just logo/title stack), and to any number of trailing full-width
       rows (`+ tr ~ tr`, kept in source order — change-order's items/totals rows land here). */
    .report-wrapper table.table-bordered:has(img[ng-src]) {
        display: block !important;
        width: 100% !important;
    }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody {
        display: grid;
        grid-template-columns: auto 1fr;   /* label (content-width) : value (fills) */
        align-items: center;
        column-gap: 10px;
    }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr {
        display: contents;
    }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr > td {
        display: block;
        width: auto !important;
        height: auto !important;
        text-align: start;
        white-space: normal;
    }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr > td[colspan] {
        grid-column: 1 / -1;   /* multi-column cells (logo/title/description/field rows) → full-width */
    }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:first-child > td { order: 1; }             /* logo */
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:nth-child(2) > td:nth-child(1) { order: 2; } /* project / site */
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:nth-child(2) > td:nth-child(2) { order: 3; } /* contract number */
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(1) { order: 4; } /* title cell */
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(2) { order: 5; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr > td:nth-child(1) { order: 6; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(3) { order: 7; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr > td:nth-child(2) { order: 8; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(4) { order: 9; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr > td:nth-child(3) { order: 10; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(5) { order: 11; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr > td:nth-child(4) { order: 12; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) > td:nth-child(6) { order: 13; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr > td:nth-child(5) { order: 14; }
    .report-wrapper table.table-bordered:has(img[ng-src]) > tbody > tr:has(td[rowspan]) + tr ~ tr > td { order: 30; } /* trailing full-width field rows, kept in source order */
    /* report templates hardcode pixel widths on some inputs/textareas (e.g.
       width:455px/500px) — clamp so they never exceed their cell/viewport. */
    #form-content .report-wrapper input,
    #form-content .report-wrapper textarea,
    #form-content .report-wrapper .form-control {
        max-width: 100%;
        box-sizing: border-box;
    }

    /* ---------------------------------------------------------------------
     * form-table (`public/directives/form/table.html`) → CARDS on phone,
     * native table on tablet/desktop. Used by every structured form table
     * (change-order line items, BOQ, etc.). Each field cell carries a
     * `data-label` stamped in the template from `table.properties[col].label`,
     * so labels survive ng-repeat / drag-sort re-renders (no DOM hacking).
     * Scoped to `.form-table-wrap` so the legacy `.report-wrapper` tables
     * (which also use `tr.report-rows`) are NOT affected.
     * ------------------------------------------------------------------- */
    /* the wrapper is Bootstrap .table-responsive: on phones it adds overflow-y:hidden
       (clipped the "Add row" button) AND a 1px #ddd border (which then ran *behind*
       the overflowing button). Cards don't scroll and carry their own borders, so drop
       both on mobile. */
    .form-table-wrap {
        overflow: visible;
        border: 0;
    }
    .form-table-wrap > table > thead {
        display: none;                 /* labels repeat per field inside each card */
    }
    .form-table-wrap > table,
    .form-table-wrap > table > tbody {
        display: block;
        width: 100%;
    }
    .form-table-wrap > table > tbody > tr.report-rows {
        display: block;
        position: relative;
        height: auto !important;   /* the table row otherwise keeps a 20px row height and clips the card */
        border: 1px solid #cfd6dd;
        border-radius: 8px;
        margin: 0 0 10px;
        background: #fff;
        overflow: hidden;          /* clip the rounded corners (safe now height is auto) */
    }
    .form-table-wrap > table > tbody > tr.report-rows > td {
        display: flex;
        align-items: center;
        gap: 12px;
        border: 0;
        border-top: 1px solid #eef1f4;
        padding: 8px 11px;
        text-align: start;
        white-space: normal;
        height: auto !important;   /* cells otherwise inherit the 20px table-row height and overlap */
        min-height: 40px;
    }
    .form-table-wrap > table > tbody > tr.report-rows > td[data-label]:not([data-label=""])::before {
        content: attr(data-label);
        flex: 0 0 auto;      /* was 0 0 38%: a fixed 38% reserved a wide empty gap next to
                                short (RTL) labels — size to the label and let the field fill */
        max-width: 42%;      /* keep a long label from crowding out the field */
        font-weight: 600;
        color: #556;
        font-size: 12px;
    }
    /* the field component fills the value side */
    .form-table-wrap > table > tbody > tr.report-rows > td > * {
        flex: 1 1 auto;
        min-width: 0;
    }
    .form-table-wrap form-field,
    .form-table-wrap form-field .form-control,
    .form-table-wrap form-field input,
    .form-table-wrap form-field select,
    .form-table-wrap form-field textarea {
        width: 100% !important;
        min-width: 0 !important;
    }
    /* card header strip = the ID cell. The drag handle (jQuery-UI sortable +
       touch-punch give real touch drag-to-reorder, same as desktop web) is floated
       into the header corner, just inline-start of the ⋮ menu. Sortable's handle
       selector is `.form-table-drag-handle`, so only the grip starts a drag — tapping
       the rest of the header still toggles collapse. */
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-drag-cell {
        position: absolute;
        top: 20px;                  /* vertically centered in the ~40px header strip */
        transform: translateY(-50%);
        inset-inline-start: 6px;    /* start edge — opposite the ⋮ menu, so they never collide */
        border: 0;
        padding: 0;
        z-index: 2;
    }
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-drag-cell .form-table-drag-handle {
        padding: 6px 8px;
        color: #9aa3ad;
        cursor: grab;
        touch-action: none;          /* let touch-punch own the gesture, no scroll hijack */
    }
    /* Sortable drop placeholder: jQuery-UI clones the dragged row's field cells into the
       placeholder but strips their classes/data-label, so the card-collapse rule can't
       hide them — the gap rendered at full (expanded) height as blank white space. Force
       a slim, clearly-marked drop zone regardless of the cloned content. */
    /* high specificity: must beat `tr.report-rows { height:auto !important }` above */
    .form-table-wrap > table > tbody > tr.report-rows.ui-sortable-placeholder {
        visibility: visible !important;   /* show the drop target instead of an invisible gap */
        height: 44px !important;
        min-height: 0 !important;
        margin: 0 0 10px !important;
        border: 2px dashed #aeb8c2 !important;
        border-radius: 8px;
        background: #eef2f5;
        box-sizing: border-box;
        overflow: hidden !important;
    }
    .form-table-wrap > table > tbody > tr.report-rows.ui-sortable-placeholder > * {
        display: none !important;         /* hide the mis-cloned field cells */
    }
    /* `.form-table-card-head` is the synthesized header for hide_id tables (no ID
       column); it renders only on mobile and shares the id-cell's header styling. */
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-id-cell,
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-card-head {
        background: #f4f7f8;
        font-weight: 700;
        color: #334;
        border-top: 0;
        cursor: pointer;            /* the header strip is the expand/collapse toggle */
    }
    /* card header layout: "Row N" on the start side, chevron on the end side */
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-id-cell .form-table-id-cell-inner,
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-card-head .form-table-id-cell-inner {
        display: flex;
        align-items: center;
        justify-content: flex-start;   /* override desktop's center; pack label+chevron to the start */
        gap: 6px;
        width: 100%;
    }
    .form-table-wrap .form-table-row-label {
        display: inline;           /* shown on mobile (hidden globally below) */
    }
    .form-table-wrap > table > tbody > tr.report-rows .form-table-card-toggle {
        display: inline-block;     /* shown on mobile (hidden globally below) */
        color: #8a929c;
        transition: transform .15s ease;
    }
    /* open card → chevron points up */
    .form-table-wrap > table > tbody > tr.report-rows:not(.form-card-collapsed) .form-table-card-toggle {
        transform: rotate(180deg);
    }
    /* collapsed card → hide the field rows, keep only the header strip */
    .form-table-wrap > table > tbody > tr.report-rows.form-card-collapsed > td[data-label] {
        display: none;
    }
    /* row ⋮ menu sits at the END (opposite the label+chevron) so they don't collide;
       reserve space on that side of the header so the label never runs under it */
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-id-cell .form-table-id-cell-inner,
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-card-head .form-table-id-cell-inner {
        padding-inline-end: 34px;   /* clear the ⋮ menu (end edge) */
        padding-inline-start: 34px; /* clear the drag grip (start edge) */
    }
    .form-table-wrap > table > tbody > tr.report-rows > .form-table-actions-cell {
        position: absolute;
        top: 20px;                  /* vertically centered in the ~40px header strip */
        transform: translateY(-50%);
        inset-inline-end: 8px;
        border: 0;
        padding: 0;
        z-index: 1;
    }
    /* the trailing "Add row" footer row */
    .form-table-wrap > table > tbody > tr:not(.report-rows) {
        display: block;
    }
    .form-table-wrap > table > tbody > tr:not(.report-rows) > td {
        display: block;
        width: 100% !important;
        border: 0;
        padding: 8px 0 0;
    }
    /* the add-row split-button menu uses uib `dropdown-append-to-body`, which moves
       the <ul> to <body> and hard-codes an inline `left` aligned to the toggle — at
       the RTL start edge that pushes the menu off the right of the screen. The class
       travels with the appended node, so pin it inside the viewport here. */
    .form-addrow-menu {
        left: auto !important;
        right: 8px !important;
    }

    /* The global mobile nav is a Bootstrap .navbar, which ships a default
       margin-bottom:20px — too big a gap above the project title row. */
    nav.main-navigation.visible-xs {
        margin-bottom: 8px;
    }

    /* Project sub-header (#3): on a phone this whole block sat below the global
       nav as a near-empty bar — a 32px title in a fixed 70px box plus an <hr>
       that only ever divided the desktop #project-buttons (hidden-xs hidden-sm,
       so empty here). Collapse it to a single compact title row so drawings
       surface higher: drop the fixed height + the orphan rule, shrink the h1. */
    #project-header {
        height: auto;
        margin-bottom: 6px;
    }
    #project-header hr {
        display: none;
    }

    /* Project header: the project-menu (≡) toggle now sits inline with the title
       (moved out of the nav below). Lay the title row out as [title] [≡]. */
    #project-details {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-bottom: 0;
    }
    #project-details #project-name {
        margin: 0;
        font-size: 18px;          /* down from the desktop 32px h1 */
        line-height: 1.2;
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;      /* long project names truncate instead of wrapping the row tall */
    }
    #project-details .project-name-menu-toggle {
        float: none;
        margin: 0;
        display: block;
        flex: 0 0 auto;
        border: 1px solid #ccc;
        border-radius: 4px;
        padding: 8px 10px;
    }
    /* the ≡ bars got their colour from `.navbar-default .navbar-toggle .icon-bar`;
       restore it now the toggle lives outside the navbar */
    #project-details .project-name-menu-toggle .icon-bar {
        background-color: #888;
    }
    /* the project-menu nav is now just the collapsible list — drop the empty
       navbar bar so nothing shows until the ≡ is tapped */
    .project-menu-collapsed.navbar {
        border: 0;
        background: none;
        min-height: 0;
        margin-bottom: 0;
    }
}

/* Desktop: the wrapper must be transparent so it doesn't break the original
   inline filename + floated icons layout (the kebab itself is ng-if="isMobile"
   and never renders here). Mobile overrides this to flex (above). */
.board-row-header {
    display: contents;
}

/* The overflow menu is styled outside the width breakpoint because it only
   ever renders on mobile (ng-if="isMobile") and may be detached from the
   .execution-board-table subtree by the dropdown. */
.board-row-actions-menu {
    min-width: 180px;
}
.board-row-actions-menu > li > a {
    padding: 6px 14px;
    font-size: 13px;
}
.board-row-actions-menu > li > a > i.fa-fw {
    margin-inline-end: 8px;   /* RTL-safe spacing between icon and label */
}

/* Form view (#form2): the mobile Actions menu. Styled outside the width
   breakpoint because it only renders on mobile (ng-if="isMobile") and the
   uib-dropdown may detach the <ul> from the #content-header subtree. */
.form-actions-menu {
    min-width: 190px;
}
.form-actions-menu > li > a {
    padding: 9px 14px;
    font-size: 14px;
}
.form-actions-menu > li > a > i.fa-fw {
    margin-inline-end: 8px;   /* RTL-safe icon/label spacing */
}
.form-actions-menu > li > a.text-danger {
    color: #b23b3b;
}

/* form-table card affordances (the "Row N" label + expand/collapse chevron) are
   mobile-card-only — hide them on tablet/desktop where the native table shows.
   The mobile rules above (inside the breakpoint) re-display them.
   `.form-table-card-head` is the synthesized header for hide_id tables: it must
   never occupy a desktop table column (the ID column is deliberately hidden), so
   it stays display:none until the phone breakpoint turns it into a header strip. */
.form-table-row-label,
.form-table-card-toggle,
.form-table-card-head {
    display: none;
}

/* ---------------------------------------------------------------------------
 * Small phone (≤ 480px)
 * ------------------------------------------------------------------------- */
@media only screen and (max-width: 480px) {
    /* Small-phone overrides go here. */
}

/* ---------------------------------------------------------------------------
 * "Get the native app" banner (mobile-browser users only)
 * -----------------------------------------------------------------------------
 * Styled OUTSIDE a width breakpoint because the element is rendered server-side
 * only when the request is a mobile browser AND a store URL exists for the OS
 * (see Module.php / docs/MOBILE-APP-BANNER.md) — it never exists on desktop.
 * Bootstrap's `.hidden` handles show/hide; the server gates the render on the
 * per-user `user_meta.mobile_app_banner` flag (1 = show, 0 = dismissed).
 * ------------------------------------------------------------------------- */
.mobile-app-banner {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 2002;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: #263238;
    color: #fff;
    box-shadow: 0 -2px 6px rgba(0, 0, 0, .2);
    font-size: 14px;
}
.mobile-app-banner .mab-icon {
    font-size: 18px;
    line-height: 1;
}
.mobile-app-banner .mab-text {
    flex: 1;
}
.mobile-app-banner .mab-install {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: 20px;
    font-weight: 600;
    font-size: 14px;
    color: #fff;
    text-decoration: none;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.mobile-app-banner .mab-install:active {
    transform: translateY(1px);
}
.mobile-app-banner .mab-store-logo {
    display: inline-block;
    vertical-align: middle;
}
/* App Store — Apple blue */
.mobile-app-banner .mab-install--ios {
    background: linear-gradient(180deg, #2b9dff 0%, #0071e3 100%);
}
/* Google Play — Play green */
.mobile-app-banner .mab-install--android {
    background: linear-gradient(180deg, #2ea06f 0%, #01875f 100%);
}
.mobile-app-banner .mab-install:hover,
.mobile-app-banner .mab-install:focus {
    color: #fff;
    filter: brightness(1.08);
}
.mobile-app-banner .mab-close {
    flex: none;
    color: #fff;
    opacity: .8;
    text-shadow: none;
    font-size: 20px;
    line-height: 1;
}
.mobile-app-banner .mab-close:hover {
    opacity: 1;
    color: #fff;
}
