/* =============================================================
   Shared responsive behaviour — loaded last, after portal.css /
   masters.css, so it can override their desktop rules.

   Breakpoints
     <= 1080px  tablet landscape and below: sidebar becomes a drawer
     <=  820px  tablet portrait: header and toolbars stack
     <=  560px  phone: tighter padding, full width controls
   ============================================================= */

/* ── Never let the page scroll sideways ──
   Only body carries overflow-x. Putting it on html turns the root into a
   scroll container, which silently kills every position:sticky on the page —
   the navbar and the sidebar included. With html left visible, body's value
   propagates to the viewport and still clips sideways, but sticky keeps
   working. */
html {
    max-width: 100%;
}

body {
    max-width: 100%;
    overflow-x: hidden;
}

/* Long words / urls in table cells must not force the page wider */
.mst-tbl td,
.mst-tbl th {
    overflow-wrap: anywhere;
}

/* ── Sidebar drawer trigger — hidden on desktop ── */
.nav-burger {
    display: none;
    width: 36px;
    height: 36px;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    border: 1px solid var(--rule);
    background: var(--white);
    color: var(--ink3);
    cursor: pointer;
    flex-shrink: 0;
    transition: .14s;
}

.nav-burger:hover {
    background: var(--bg);
    color: var(--ink);
}

/* ── Drawer backdrop ── */
.ui-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(22, 33, 30, .45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s;
    z-index: 250;
}

body.nav-open .ui-backdrop {
    opacity: 1;
    pointer-events: auto;
}

/* =============================================================
   <= 1080px — sidebar off canvas
   ============================================================= */
@media (max-width: 1080px) {

    .nav-burger {
        display: inline-flex;
    }

    /* portal.css hides .sidenav outright at this width; bring it back as a
       drawer that slides in from the left instead. */
    .sidenav {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: var(--nav-h);
        left: 0;
        bottom: 0;
        width: min(282px, 84vw);
        transform: translateX(-100%);
        transition: transform .22s ease;
        z-index: 300;
        box-shadow: 0 18px 50px rgba(22, 33, 30, .18);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    body.nav-open .sidenav {
        transform: none;
    }

    /* Give the drawer room to breathe and keep tap targets comfortable */
    .sidenav .snl,
    .sidenav .subnav a {
        min-height: 42px;
    }

    .main {
        width: 100%;
        min-width: 0;
    }
}

/* =============================================================
   <= 820px — header, toolbars and modals stack
   ============================================================= */
@media (max-width: 820px) {

    /* Page header: title above the action buttons */
    .page-hdr {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
        padding: 14px 16px;
    }

    .page-hdr-right {
        margin-left: 0;
        flex-wrap: wrap;
    }

    .page-title {
        font-size: 17px;
    }

    /* Master screens */
    .mst-main {
        padding: 16px;
    }

    /* List card: title over its own toolbar, search goes full width */
    .lc-hd {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

    .lc-hd-right {
        flex-direction: column;
        align-items: stretch;
    }

    .lc-search {
        width: 100%;
    }

    .lc-hd-right .abtn {
        justify-content: center;
    }

    .lc-tools {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

    /* The date range gets its own line; the label stays beside its input */
    .lc-tools .dt-filters {
        justify-content: flex-start;
        flex: none;
    }

    .lc-tools .dt-filters .fgroup {
        flex: 1 1 190px;
    }

    .lc-show,
    .lc-page {
        justify-content: space-between;
    }

    /* "More filters" and its panel stack rather than squeeze */
    .lc-more {
        order: -1;
        justify-content: center;
    }

    .lc-extra .fgroup {
        flex: 1 1 210px;
    }

    .lc-extra .fsel {
        flex: 1;
        max-width: none;
    }

    .lc-body {
        padding: 14px;
    }

    .mst-bar {
        gap: 8px;
    }

    .mst-search {
        min-width: 0;
        flex: 1 1 100%;
    }

    .mst-filter {
        flex: 1 1 auto;
    }

    /* Modals: use the width, keep a little margin */
    .ack-overlay {
        align-items: flex-end;
        padding: 0;
    }

    .ack-modal {
        max-width: 100% !important;
        width: 100%;
        border-radius: 18px 18px 0 0;
        max-height: 92vh;
        overflow-y: auto;
    }

    .ack-modal-ft {
        position: sticky;
        bottom: 0;
        flex-wrap: wrap;
    }

    .ack-modal-ft .abtn {
        flex: 1 1 auto;
        justify-content: center;
    }

    /* Two column form rows become one */
    .frow,
    .frow.three {
        grid-template-columns: 1fr;
    }

    /* Auth pages already collapse at 900px; keep the card comfortable */
    .auth-panel {
        padding: 32px 20px;
    }
}

/* =============================================================
   <= 560px — phone
   ============================================================= */
@media (max-width: 560px) {

    .mst-main {
        padding: 12px;
    }

    .page-hdr {
        padding: 12px;
    }

    /* Buttons in the header go full width so they are easy to hit */
    .page-hdr-right .abtn {
        flex: 1 1 100%;
        justify-content: center;
    }

    .mst-bar .abtn {
        flex: 1 1 auto;
        justify-content: center;
    }

    /* List card: tighter, and the row lift is dropped — it only smears
       on a touch screen where there is no hover to begin with */
    .lc-body {
        padding: 12px;
    }

    .lc-show,
    .lc-info {
        font-size: 12px;
    }

    .lc-show select {
        flex: 1;
        width: auto;
    }

    .lc-card table.dataTable tbody tr:hover {
        transform: none;
        box-shadow: none;
    }

    /* Navbar: drop the profile text, keep avatar + actions */
    .prof-nm,
    .prof-rl {
        display: none;
    }

    .prof-btn {
        padding: 3px;
    }

    .nav {
        padding-right: 12px;
    }

    .brand {
        width: auto;
        border-right: none;
        padding: 0 12px;
    }

    .epoch-logo {
        width: 88px;
    }

    /* Menu picker gets more room */
    .mst-pick {
        max-height: 46vh;
    }

    /* Dialling code sits above the number on the narrowest screens */
    .mst-phone {
        flex-wrap: wrap;
    }

    /* flex-basis again, for the same reason the base rule uses it — width
       alone would leave the 112px basis in charge and the pair would not
       stack. */
    .mst-phone-code {
        flex: 1 1 100%;
        width: 100%;
    }

    .mst-phone-number {
        flex: 1 1 100%;
    }

    /* Permission matrix: label above the level dropdown */
    .perm-row {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding: 12px 14px;
    }

    .perm-sel {
        width: 100%;
        height: 40px;
    }

    .perm-save {
        flex-direction: column;
        align-items: stretch;
    }

    .perm-save .abtn {
        justify-content: center;
    }

    .auth-title {
        font-size: 20px;
    }
}

/* Respect users who ask for less motion */
@media (prefers-reduced-motion: reduce) {

    .sidenav,
    .ui-backdrop {
        transition: none;
    }
}

/* ── Bulk upload: the two steps stack once the row gets tight ── */
@media (max-width: 820px) {
    .lc-up-grid {
        grid-template-columns: 1fr;
        gap: 18px;
    }

    .lc-up-pick .finp {
        flex: 1 1 100%;
    }

    .lc-up-pick .abtn {
        flex: 1 1 100%;
        justify-content: center;
    }
}

/* ── Customer form: the repeating rows and the save bar ── */
@media (max-width: 820px) {
    .rep-row {
        padding: 12px;
    }

    .lc-form-ft {
        position: static;
        flex-direction: column-reverse;
        align-items: stretch;
        padding: 12px;
    }

    .lc-form-ft .abtn {
        justify-content: center;
    }
}

/* ── Record tabs: scroll sideways rather than wrap ── */
@media (max-width: 560px) {
    .lc-tabs {
        padding: 0 12px;
    }

    .lc-tab {
        padding: 12px 12px;
        font-size: 12.5px;
    }
}

/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   LEAD WORKFLOW  â€”  stage 1 and stage 2 on the lead view

   The two field grids are auto-fit, so they reflow on their own. What is
   left is the rows that are flex: the reassign row and the two confirm
   bars, which otherwise leave a button stranded on its own line, and the
   tab bar, which needs its padding pulled in on a phone.
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

@media (max-width: 820px) {
    /* The reassign controls stop competing for width and take a line each.
       A select showing "name â€” 2/5 active, 96% successâ€¦" is unreadable at
       half a phone's width. */
    .lw-move .abtn {
        justify-content: center;
        width: 100%;
    }

    /* The engineer rows carry five things on one line; below this they
       need the whole width, and the panel needs the whole dialog. */
    .lw-engdd-panel {
        max-height: 60vh;
    }

    .lw-engstats {
        gap: 6px 10px;
    }

    /* The dialog's two numbers stack rather than sharing a narrow row. */
    .lw-dlg-bd .lw-fields {
        grid-template-columns: 1fr;
    }

    .lw-teambar {
        align-items: stretch;
        flex-direction: column;
    }

    .lw-teambar .abtn {
        justify-content: center;
    }

    /* Guidance text above the button rather than beside it, so the button
       keeps a full-width tap target. */
    .lw-actions {
        align-items: stretch;
        flex-direction: column;
    }

    .lw-actions .fgroup,
    .lw-actions-note {
        min-width: 0;
        width: 100%;
    }

    .lw-actions .abtn {
        justify-content: center;
        width: 100%;
    }

    .lw-summary {
        gap: 14px 22px;
    }
}

@media (max-width: 560px) {
    /* Tabs scroll sideways rather than wrap â€” same as .lc-tabs above. */
    .lw-tab {
        padding: 11px 12px;
        font-size: 12.5px;
    }

    .lw-card-bd,
    .lw-job-bd {
        padding: 12px;
        gap: 10px;
    }

    .lw-item {
        padding: 12px 13px;
    }

    .lw-group-bd {
        padding: 9px 9px 1px;
    }

    .lw-job-hd {
        padding: 10px 12px;
    }

    /* The job code and the item name stop sharing a line: at this width
       the code was pushing the name down to one word per line. */
    .lw-job-hd {
        align-items: flex-start;
        flex-direction: column;
        gap: 7px;
    }

    .lw-job-hd .lw-nm {
        min-width: 0;
    }

    /* Put-back sits under the terms box rather than beside it: at this width
       the two side by side left the box too narrow to read a sentence in. */
    .qt-terms {
        align-items: stretch;
        flex-direction: column;
    }

    .qt-reterms {
        width: 100%;
        height: 34px;
    }

    /* The terms surface stacks: the Change button on its own line rather
       than squeezing the set name into three words. */
    .qt-tc {
        align-items: flex-start;
        flex-wrap: wrap;
        gap: 10px;
    }

    .qt-tc-main {
        flex: 1 1 100%;
        order: 3;
    }

    .qt-tc-cta {
        margin-left: auto;
    }

    .qt-tc-read {
        max-height: 180px;
    }

    /* The held-for-a-price line and the accepted line both read as a
       sentence, so at this width the icon goes above it rather than
       squeezing the words into a column two characters wide. */
    .lw-lock {
        align-items: flex-start;
        padding: 10px 12px;
        line-height: 1.5;
    }

    .lw-bulk-top {
        align-items: flex-start;
        flex-direction: column;
        gap: 8px;
    }

    /* Clear was pushed to the far right by margin-left:auto, which on a
       stacked column puts it on its own line miles from the count. */
    .lw-bulk-clear {
        margin-left: 0;
    }

    /* Two full-width rows rather than two squeezed columns — at this width
       neither label fits on one line. */
    .lw-modes {
        flex-direction: column;
    }

    /* Every category button on one row still, but tighter: three of them
       wrapping to two lines reads as two groups rather than one choice. */
    .lw-cat {
        padding: 7px 10px;
        font-size: 11.5px;
    }

    .lw-card-hd {
        padding: 12px;
        gap: 10px;
    }

    /* On a touch screen there is no hover, so the "waiting for signature"
       message has nothing to reveal it. It stays up. */
    .lw-gate-msg {
        top: 76px;
        max-width: none;
        padding: 14px 16px;
    }
}

/* Same on any pointerless device, whatever its width — a tablet is wide
   enough to miss the rule above and still has nothing to hover with. */
@media (hover: none) {
    .lw-gate.locked .lw-gate-msg {
        opacity: 1;
        transform: none;
    }
}

/* ── Quotation builder ─────────────────────────────────────────────────
   The document's three-up header and the notes-beside-totals split are the
   two things that cannot survive a narrow screen. Both collapse to one
   column; the lines table keeps its min-width and scrolls inside its own
   wrapper rather than pushing the page sideways. */

@media (max-width: 1080px) {
    .qt-grid { grid-template-columns: repeat(2, 1fr) }
    .qt-bottom { grid-template-columns: 1fr }
}

@media (max-width: 820px) {
    .qt-brandrow { flex-direction: column; gap: 14px }
    .qt-brandmeta { gap: 18px }
    .qt-grid { grid-template-columns: 1fr }
    .qt-revise { flex: 1 1 100% }
}

@media (max-width: 560px) {
    .qt-brandmeta { flex-direction: column; gap: 10px }
    .qt-tr .finp, .qt-tr .fsel { max-width: 108px }
    .qt-grand { font-size: 14px }
    .qt-grand b { font-size: 15px }
}

/* ── Quotation list: the lead row and its jobs ─────────────────────────
   The action column is the first thing to go: on a narrow screen the row
   itself is the control, and the jobs fold out under it either way. */

@media (max-width: 820px) {
    .qx-act .abtn { padding: 6px 10px; font-size: 12px }
    .qx-jobcode { padding-left: 10px !important }
}

@media (max-width: 560px) {
    .qx-n { display: block; margin-left: 0 }
}

/* ── Quotation view pages ──────────────────────────────────────────────
   The gap between stacked blocks tightens with the screen, so a card that
   holds a grid, a note and a button does not become mostly whitespace. */

@media (max-width: 820px) {
    .qt-page .lw-card-bd > * + * { margin-top: 13px }
}

@media (max-width: 560px) {
    .qt-page .lw-card-bd > * + * { margin-top: 11px }
}

/* ── Followup timeline ─────────────────────────────────────────────────
   The author's name drops under the header row rather than being pushed
   off the end of it. */

@media (max-width: 560px) {
    .fu-by { margin-left: 0; width: 100% }
    .fu-entry-ft { gap: 8px }
}
