/* ============================================================================
   DOFT Loadboard — screenshot regression pass, 2026-08-17
   Loaded LAST. Fixes only what the 18:11-19:06 dev screenshots reproduced.

   Read this before touching the sticky header or the split buttons: both were
   made worse by the 2026-08-15 pass, and both are fixed here at the mechanism
   level rather than with another round of pixel offsets.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   1) STICKY TABLE HEADER — the real header, in flow, never a fixed copy.

   Measured on the 19:05:59 (unstuck) / 19:06:14 (stuck) pair: unstuck, every
   header boundary sits on the body's to the pixel. Stuck, the header's gray band
   runs to the WINDOW edge instead of the table's, ORIGIN and DESTINATION each
   absorb ~11px of the surplus, and every boundary from WT rightwards lands ~22px
   off. That is what `position: fixed` does — out of flow, the header's width no
   longer comes from the table.

   refresh.css:990 already declares `position: sticky` for the header at >=768px,
   and doft_helpers.js no longer pins in refresh mode, so this file only has to
   make sure sticky can actually work and cannot be knocked out again.
   ---------------------------------------------------------------------------- */

/* No overflow rule is needed below 992px, and adding one would be false comfort.
   Checked all nine grids: eight load refresh-loads.css, which sets
   `#dTable .t-head { display: none }` under 992 and flows the rows as cards — there
   is no header to stick. The ninth, dispatch/drivers, does not load that sheet, but
   its own pages/dispatch/drivers.css:194 declares #dTable with no `overflow` at all,
   so sticky already works there at every width. `overflow: hidden` on #dTable comes
   from pages/loads.css:76 and is only in play >=992, where refresh.css:1065 already
   replaces it with `visible`. */

/* z-index 6 (refresh.css:990) was never actually exercised: the legacy fixed
   header used 100 and always won. Give the sticky header comfortable headroom
   over page chrome while staying far below Bootstrap's dropdowns (1000), which
   must still open over it. */
@media (min-width: 768px) {
  html[data-refresh] #dTable .t-head { z-index: 20; }
}

/* Safety net. If any page ever puts .fixed-header back on the table header —
   stale cached JS, a page script we have not seen — return it to sticky rather
   than let it become a viewport-wide bar again. Deliberately NOT `display: none`:
   a missing header is a worse failure than a misaligned one, and #drivers_map
   uses the same class for its own (intended) pinning, which this cannot touch. */
html[data-refresh] #dTable .t-head.fixed-header {
  position: sticky !important;
  top: var(--wow-sticky-top, 0px) !important;
  left: auto !important;
  right: auto !important;
  width: auto !important;
  z-index: 20 !important;
}

/* ----------------------------------------------------------------------------
   2) SPLIT BUTTONS — exactly one seam, and only where there is a real split.

   refresh.js normalizeActionGroups guarantees a single shape: a split control is
   a .btn-group.wow-more-group holding [primary][.act-more-toggle][.dropdown-menu],
   and it is the LAST child of the row. Anything else is a standalone pill.

   The seam is ONE border, not two overlapped by a negative margin. Negative
   margins are what produced the double line: they depend on both borders existing
   and on no other sheet adding spacing, and the result differed per engine.
   Dropping the primary's right border means the worst case is a gap, never a
   second line.
   ---------------------------------------------------------------------------- */
html[data-refresh] .load-actions > .btn-group.wow-more-group {
  display: inline-flex !important;
  align-items: stretch !important;
  flex: 0 0 auto !important;
  gap: 0 !important;
  margin: 0 !important;
  white-space: nowrap !important;
  /* Far right of the action row: the "…"/caret is the last control on the line.
     normalizeActionGroups already appends the group last in the DOM (so tab order
     matches what is on screen); this only covers the first paint, before the
     script has run, and any row the observer has not reached yet. */
  order: 99 !important;
}
html[data-refresh] .load-actions > .btn-group.wow-more-group > .btn:not(.act-more-toggle),
html[data-refresh] .load-actions > .btn-group:has(> .act-more-toggle) > .btn:not(.act-more-toggle) {
  /* 18px outer end matches the toggle's 18px and the standalone pills, so the pair
     reads as ONE control. This is already round7's shipper geometry (round7:43-47);
     the driver's primary was left at the base 12px and looked slightly clipped. */
  border-top-left-radius: 18px !important;
  border-bottom-left-radius: 18px !important;
  border-top-right-radius: 0 !important;
  border-bottom-right-radius: 0 !important;
  border-right: 0 !important;   /* the single seam is the toggle's left border */
  margin: 0 !important;
}
html[data-refresh] .load-actions > .btn-group.wow-more-group > .act-more-toggle,
html[data-refresh] .load-actions > .btn-group:has(> .btn:not(.act-more-toggle)) > .act-more-toggle {
  position: relative !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  flex: 0 0 42px !important;
  width: 42px !important;
  min-width: 42px !important;
  max-width: 42px !important;
  margin: 0 !important;
  padding: 0 !important;
  border-left-width: 1px !important;
  border-left-style: solid !important;
  border-top-left-radius: 0 !important;
  border-bottom-left-radius: 0 !important;
  border-top-right-radius: 18px !important;
  border-bottom-right-radius: 18px !important;
  line-height: 1 !important;
}
html[data-refresh] .load-actions > .btn-group.wow-more-group > .act-more-toggle::after,
html[data-refresh] .load-actions > .btn-group:has(> .act-more-toggle) > .act-more-toggle::after {
  position: static !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  margin: 0 !important;
  transform: none !important;
  line-height: 1 !important;
}

/* Every load-action button is a pill; the two rules above then square only the two
   inner corners of a real split pair (they are more specific, so order does not
   matter). Written this way so a standalone action — AI Status Call, AI Invoice
   Call, Post, Unpost, Refresh, Book Now, and a lone "…" with no primary to pair
   with — is round on both ends by default rather than by exception. */
html[data-refresh] .load-actions .btn {
  border-radius: 18px !important;
}

/* Note the second selector in each of the three rules above: it keys on the markup
   (`a group that contains a toggle`) rather than on the class refresh.js adds. That is
   deliberate. If the script never runs, the server's already-correct one-group shape
   still renders as a proper split button, and the two-group shape falls back to two
   separate pills — the pre-08-15 appearance, not a broken one. Only the ORDER below
   depends on the script. Single-level :has() only; round7:38-70 has shipped the same
   construct for the shipper since 29 July. */

/* ----------------------------------------------------------------------------
   3) DRIVER MY LOADS — group boundary before PRICE.
   The STATUS caption itself is markup (driver/my-loads-page.js). On the
   non-active tabs the column left of PRICE is .c-addr, which pages/loads.css:114
   deliberately strips the divider from, so the header showed no boundary where
   the body has one. Put it back on the block, not on the cell.
   ---------------------------------------------------------------------------- */
@media (min-width: 992px) {
  html[data-refresh] .my-loads-page #dTable .t-head .cb-price {
    border-left: 1px solid var(--line, #eee);
  }
  html[data-refresh] .my-loads-page #dTable .t-head .c-status {
    justify-content: flex-start;
  }
}

/* ----------------------------------------------------------------------------
   4) EXPANDED LOAD — Call / AI Call align with the CONTACT VALUE.
   GetLoadPageAjax now emits .hdr.phone-action-hdr-spacer with an inline
   visibility:hidden instead of display:none. Match the real .hdr metrics so the
   phone column keeps the same label row height the contact column has; no
   `top` offsets anywhere.
   ---------------------------------------------------------------------------- */
html[data-refresh] .contact-phone-row .phone-action-hdr-spacer {
  display: block !important;
  visibility: hidden !important;
  pointer-events: none !important;
}

/* ----------------------------------------------------------------------------
   5) MAP POPUP — phone and AI robot are not glued together.
   refresh.js callHtml() clones `#dTable .cb-contactlinks`'s innerHTML into the
   HERE popup. Outside #dTable the table-scoped gap rules (round5 §, round10 §)
   no longer match, so the two icons fell back to their natural inline spacing.
   8px matches the popup's own action gap, giving phone <8> robot <8> View details.
   ---------------------------------------------------------------------------- */
.doft-map-popup .c-contactlinks,
.doft-map-popup .cb-contactlinks {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
}
.doft-map-popup__actions { gap: 8px !important; }

/* ----------------------------------------------------------------------------
   6) POST SHIPMENTS IN BULK — wrap by meaning below 1200px.

   Round 11 held the desktop single row all the way down to 992px by shrinking
   fixed-width fields (price 60px, ref 60px, desc 92px). That is what made TL/LTL
   unreadable, Ref/Desc collide and Price hard to hit. Owner decision 2026-08-17:
   below 1200px use the card's width and let the row wrap into logical lines.

   ⚠ The .filter-option chain below MUST keep width:100% / min-width:0 /
   overflow:hidden AND the padding reset. This is bootstrap-select 1.13.2
   (LoadPostBulkPage.jsp:17), where .filter-option is position:absolute;left:0;
   width:100%. Round 11.1 gave it min-width:max-content;overflow:visible, and that
   positioned box then painted and hit-tested over the Price input next to it —
   every click in Price opened TL/LTL. And without zeroing the padding the vendor
   inherits at every level, the same control collapses the label to a single "L",
   which is the bug round 11.1 existed to fix. Both halves are required.
   ---------------------------------------------------------------------------- */
@media (min-width: 768px) and (max-width: 1199.98px) {
  html[data-refresh] .bulk-post-page .load-inner {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: flex-start !important;
    align-content: flex-start !important;
    gap: 10px 8px !important;
  }
  html[data-refresh] .bulk-post-page .load-inner > :is(
    .date-block, .wp-points-wrp, .truck-type-wrp, .price-wrp, .desc-block, .features-block
  ) {
    margin: 0 !important;
    align-self: flex-start !important;
  }

  html[data-refresh] .bulk-post-page .date-block { flex: 0 0 auto !important; }
  html[data-refresh] .bulk-post-page .load-inner > .wp-points-wrp {
    flex: 1 1 360px !important;
    min-width: 300px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .wp-points-wrp > .d-flex { width: 100% !important; }
  html[data-refresh] .bulk-post-page .wp-points-wrp > .d-flex > div { flex: 1 1 50% !important; min-width: 0 !important; }
  html[data-refresh] .bulk-post-page .wp-points-wrp :is(.pickup, .dropoff) { width: 100% !important; }

  html[data-refresh] .bulk-post-page .pu-date,
  html[data-refresh] .bulk-post-page .pu-time {
    width: 88px !important;
    min-width: 88px !important;
    max-width: 88px !important;
  }

  html[data-refresh] .bulk-post-page .truck-type-wrp,
  html[data-refresh] .bulk-post-page .price-wrp {
    display: flex !important;
    flex: 0 0 auto !important;
    align-items: flex-start !important;
    gap: 8px !important;
    min-width: 0 !important;
  }
  html[data-refresh] .bulk-post-page .truck-type-block,
  html[data-refresh] .bulk-post-page .truck-type-block .bootstrap-select,
  html[data-refresh] .bulk-post-page .truck-type-block .bootstrap-select > .dropdown-toggle {
    width: 146px !important;
    min-width: 146px !important;
    max-width: 146px !important;
  }
  /* Pin the weight block to the sum of its two controls. Left to intrinsic sizing it
     came out 150px while its .input-group children add up to 178 (86 + 92): the group
     then overflowed 28px to the RIGHT, straight across the Price field next to it —
     the same "clicking Price hits TL/LTL" overlap the 08-15 pass fixed at >=1200. The
     l-blocks must not shrink either, or the sum is squeezed again. */
  html[data-refresh] .bulk-post-page .truck-type-wrp > .l-block,
  html[data-refresh] .bulk-post-page .price-wrp > .l-block {
    flex: 0 0 auto !important;
    margin-right: 0 !important;
  }
  html[data-refresh] .bulk-post-page .weight-block,
  html[data-refresh] .bulk-post-page .weight-block .input-group {
    width: 178px !important;
    min-width: 178px !important;
    max-width: 178px !important;
    flex: 0 0 178px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .weight {
    width: 86px !important;
    min-width: 86px !important;
    max-width: 86px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .bootstrap-select,
  html[data-refresh] .bulk-post-page .weight-block .load-size,
  html[data-refresh] .bulk-post-page .weight-block .load-size > .dropdown-toggle,
  html[data-refresh] .bulk-post-page .weight-block button.dropdown-toggle {
    width: 92px !important;
    min-width: 92px !important;
    max-width: 92px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .load-size :is(.filter-option, .filter-option-inner, .filter-option-inner-inner) {
    flex: 1 1 auto !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    overflow: hidden !important;
    text-overflow: clip !important;
    white-space: nowrap !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  html[data-refresh] .bulk-post-page .price {
    width: 92px !important;
    min-width: 92px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .ref-num {
    width: 100px !important;
    min-width: 100px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .desc-block { flex: 1 1 160px !important; min-width: 130px !important; }
  html[data-refresh] .bulk-post-page .desc-ctrl {
    width: 100% !important;
    min-width: 130px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .load-inner > .features-block {
    flex: 0 0 auto !important;
    min-width: 70px !important;
  }
}

/* Narrow / mobile: same idea, one semantic group per line where needed. */
@media (max-width: 767.98px) {
  html[data-refresh] .bulk-post-page .load-inner {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: flex-start !important;
    gap: 12px 8px !important;
  }
  html[data-refresh] .bulk-post-page .date-block,
  html[data-refresh] .bulk-post-page .load-inner > .wp-points-wrp {
    flex: 1 1 100% !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .wp-points-wrp > .d-flex { width: 100% !important; }
  html[data-refresh] .bulk-post-page .wp-points-wrp > .d-flex > div { flex: 1 1 50% !important; min-width: 0 !important; }
  html[data-refresh] .bulk-post-page .wp-points-wrp :is(.pickup, .dropoff) { width: 100% !important; }
  html[data-refresh] .bulk-post-page .truck-type-wrp {
    display: flex !important;
    flex: 1 1 100% !important;
    gap: 8px !important;
    min-width: 0 !important;
  }
  html[data-refresh] .bulk-post-page .truck-type-block,
  html[data-refresh] .bulk-post-page .truck-type-block .bootstrap-select,
  html[data-refresh] .bulk-post-page .truck-type-block .bootstrap-select > .dropdown-toggle {
    width: 148px !important;
    min-width: 148px !important;
    max-width: 148px !important;
  }
  html[data-refresh] .bulk-post-page .truck-type-wrp > .l-block,
  html[data-refresh] .bulk-post-page .price-wrp > .l-block {
    flex: 0 0 auto !important;
    margin-right: 0 !important;
  }
  /* 92 + 92; see the tablet block above for why this is stated and not inferred. */
  html[data-refresh] .bulk-post-page .weight-block,
  html[data-refresh] .bulk-post-page .weight-block .input-group {
    width: 184px !important;
    min-width: 184px !important;
    max-width: 184px !important;
    flex: 0 0 184px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .weight {
    width: 92px !important;
    min-width: 92px !important;
    max-width: 92px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .bootstrap-select,
  html[data-refresh] .bulk-post-page .weight-block .load-size,
  html[data-refresh] .bulk-post-page .weight-block .load-size > .dropdown-toggle,
  html[data-refresh] .bulk-post-page .weight-block button.dropdown-toggle {
    width: 92px !important;
    min-width: 92px !important;
    max-width: 92px !important;
  }
  html[data-refresh] .bulk-post-page .weight-block .load-size :is(.filter-option, .filter-option-inner, .filter-option-inner-inner) {
    flex: 1 1 auto !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    overflow: hidden !important;
    text-overflow: clip !important;
    white-space: nowrap !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  html[data-refresh] .bulk-post-page .price-wrp {
    display: flex !important;
    flex: 0 0 auto !important;
    gap: 8px !important;
  }
  html[data-refresh] .bulk-post-page .price {
    width: 96px !important;
    min-width: 96px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .ref-num {
    width: 104px !important;
    min-width: 104px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .desc-block { flex: 1 1 100% !important; min-width: 130px !important; }
  html[data-refresh] .bulk-post-page .desc-ctrl {
    width: 100% !important;
    min-width: 130px !important;
    max-width: none !important;
  }
  html[data-refresh] .bulk-post-page .load-inner > .features-block {
    flex: 0 0 auto !important;
    min-width: 72px !important;
  }
}

/* ----------------------------------------------------------------------------
   7) THEME SWITCH LEAVING HALF THE PAGE ON THE OLD CANVAS (Safari).

   Reported flow: load /signup in light, expand Business/Individual, switch to
   dark — everything from the Business/Individual row down keeps the light
   canvas, while the controls inside it turn dark correctly.

   The whole application's page background is ONE paint: `body { background-color:
   var(--canvas) }` (refresh.css:173, re-asserted for dark at :850). Every content
   wrapper above it is transparent — there is no background rule on .app-content,
   .content-wrapper or .content-body anywhere in the tree, and the signup card has
   none either. So the page's colour is whatever body painted, showing through.

   That is fine until a subtree gets its own compositing layer. jQuery's slideDown
   does exactly that (signup.js:35-44 slides #step_3 and #companyBlock), and WebKit
   can keep the canvas it had already composited behind that layer when the only
   thing that changed is a custom property on :root. The user's screenshots show the
   signature precisely: everything with its OWN background — the inputs, the
   .form-section bars, the .separator-txt chip — repainted dark; only the
   transparent regions kept the old #f7f8fa. That near-white, not #fff, is
   --gray-50, i.e. the light --canvas: it is stale body paint, not a white card.

   Verified in Chrome through the real flow (click DRIVER -> BUSINESS -> footer
   toggle, driving R.toggleTheme itself): no element carries a light background in
   either theme, so this is not a missing dark rule. Adding one would have been the
   wrong fix; giving these regions an explicit background of the SAME colour body
   already paints is a no-op visually and moves them into the category that did
   repaint correctly.

   Same exposure anywhere a jQuery slide/fade runs and the theme is then toggled:
   DriverPage, TruckPage, HomePage, LoadPage, LoadPostPreviewPage,
   SecondaryUserInvitePage, MyPrivateLoadboardPage, MyTruckPage, factoring/ApplyPage,
   promotions/PromotionsPage, seo/ResultsPage, plus reviews.js, load.js, driver.js,
   private-loadboard.js, truck.js, rate-check.js and shipper/loads-page.js. Painting
   the shared wrappers covers all of them.
   ---------------------------------------------------------------------------- */
/* The two values below are the colours body ALREADY paints, so this is a no-op to
   look at and only changes who owns the paint. Light is #fff, not var(--canvas):
   style.css:6 `html body { background-color: #FFFFFF }` outranks refresh.css:173's
   `body { background-color: var(--canvas) }` on specificity, so --canvas never
   reaches the light canvas. Dark is var(--canvas), which refresh.css:850 sets with
   !important. Measured both in Chrome before choosing them — painting these regions
   var(--canvas) in light would have put a #f7f8fa card on a #fff page.

   .dft-wrapper is the one that actually matters and was missing in the first cut:
   .app-content is a centred bootstrap .container, so painting it left the canvas
   visible in the margins either side of it — two white vertical strips at wide
   viewports that disappeared as soon as the window narrowed enough for the container
   to fill it. .dft-wrapper (header.jsp:393, style.css:609 `min-width:100%;
   min-height:100%`) wraps the whole page on every screen that renders a footer, so it
   covers the full viewport and there is no bare canvas left to show a stale paint. */
html[data-refresh] .dft-wrapper,
html[data-refresh] :is(.app-content, .content-wrapper, .content-body),
html[data-refresh] .doft-signup-page,
html[data-refresh] .doft-signup-page .su-max-width,
html[data-refresh] .doft-signup-page :is(#step_2, #step_3, #form-wrapper) {
  background-color: #fff;
}
html[data-theme="dark"][data-refresh] .dft-wrapper,
html[data-theme="dark"][data-refresh] :is(.app-content, .content-wrapper, .content-body),
html[data-theme="dark"][data-refresh] .doft-signup-page,
html[data-theme="dark"][data-refresh] .doft-signup-page .su-max-width,
html[data-theme="dark"][data-refresh] .doft-signup-page :is(#step_2, #step_3, #form-wrapper) {
  background-color: var(--canvas);
}
