/* ============================================================================
   FFA Shiny App — Red & Grey Theme (Bootstrap 5 / bslib)
   ============================================================================ */

/* ---------- Brand Logo ---------- */
.brand-logo {
  width: 45px;
  height: 45px;
  border-radius: 50%;
  background-color: #ffffff;
  padding: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  margin-right: 10px;
  vertical-align: middle;
  object-fit: contain;
}

/* ---------- Open / Save / Refresh Buttons ---------- */
.btn-refresh,
a.btn-refresh {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: all 0.3s ease;
  cursor: pointer;
  text-decoration: none;
}

.btn-refresh:hover,
a.btn-refresh:hover {
  background-color: rgba(255, 255, 255, 0.35);
  border-color: rgba(255, 255, 255, 0.6);
  color: white;
}

/* Only rotate the refresh icon on hover */
#refresh_app:hover {
  transform: rotate(90deg);
}

.btn-refresh:focus,
a.btn-refresh:focus {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.3);
  color: white;
}

/* ---------- Navbar ---------- */
.navbar {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.navbar .navbar-brand {
  font-weight: 600;
  font-size: 18px;
  letter-spacing: 0.3px;
}

.navbar-nav .nav-link {
  font-weight: 500;
  font-size: 14px;
  padding: 10px 16px !important;
  transition: all 0.3s ease;
}

.navbar-nav .nav-link:hover {
  background-color: rgba(255, 255, 255, 0.15);
  border-radius: 6px;
}

.navbar-nav .nav-link.active {
  background-color: rgba(255, 255, 255, 0.2) !important;
  border-radius: 6px;
}

.dropdown-menu {
  border: none;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  border-radius: 8px;
  padding: 8px;
}

.dropdown-item {
  border-radius: 6px;
  padding: 8px 16px;
  font-weight: 500;
  transition: all 0.2s ease;
}

.dropdown-item:hover,
.dropdown-item:focus {
  background-color: rgba(192, 57, 43, 0.1);
  color: #8B1A1A;
}

.dropdown-item.active,
.dropdown-item:active {
  background-color: #C0392B;
  color: white;
}

/* ---------- Cards ---------- */
.card {
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
  transition: box-shadow 0.3s ease;
}

/* "Coming soon" upload cards on the Upload Data tab */
.future-upload-card {
  opacity: 0.65;
  background: linear-gradient(180deg, #ffffff 0%, #fafbfc 100%);
}
.future-upload-card .card-header { color: #6c757d !important; }
.future-upload-card .badge.bg-secondary {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

/* Move bslib card "Expand" (full_screen) button from bottom-right to top-right */
.bslib-full-screen-enter {
  top: 0.5rem !important;
  right: 0.5rem !important;
  bottom: auto !important;
  left: auto !important;
}

/* ============================================================================
   Leaflet chrome — vault Sarawak style (Sarawak_Interactive_Map.html final look)
   ============================================================================ */

.leaflet-container {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.leaflet-control { font-family: inherit; }

/* North arrow — circle, soft slate border, soft shadow */
.leaflet-control.north-control {
  background: transparent !important;
  box-shadow: none !important;
  margin: 10px !important;
}
.north-symbol {
  background: white;
  border: 1px solid #e2e8f0;
  border-radius: 50%;
  width: 50px; height: 50px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 16px rgba(15, 23, 42, 0.14);
}
.north-arrow {
  text-align: center; color: #0f172a; font-weight: bold;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
.arrow-pointer { font-size: 16px; line-height: 1; margin-bottom: -2px; }
.north-text    { font-size: 12px; line-height: 1; font-family: Arial, sans-serif; }

/* Layer control card */
.leaflet-control-layers {
  border-radius: 12px !important;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.10), 0 1px 3px rgba(15, 23, 42, 0.06) !important;
  border: 1px solid rgba(226, 232, 240, 0.8) !important;
}

/* Minimap card */
.leaflet-control-minimap {
  border-radius: 12px !important;
  overflow: hidden;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.12) !important;
  border: 1px solid rgba(226, 232, 240, 0.8) !important;
}

/* Scale bar — frosted background, soft shadow */
.leaflet-control-scale-line {
  background: rgba(255, 255, 255, 0.95) !important;
  border: none !important;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.1);
  border-radius: 4px !important;
  font-weight: 500;
  padding: 1px 6px !important;
}

.card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.card-header {
  font-size: 16px;
  font-weight: 600;
  color: #8B1A1A;
  background-color: transparent;
  border-bottom: 2px solid #e8ecf1;
  display: flex;
  align-items: center;
  gap: 10px;
}

.card-header i,
.card-header .fa {
  font-size: 18px;
  color: #C0392B;
}

/* ---------- Sidebar (bslib layout_sidebar) ---------- */
.bslib-sidebar-layout > .sidebar {
  background-color: #f8f9fa;
  border-right: 1px solid #e8ecf1;
}

.sidebar .sidebar-title {
  font-weight: 600;
  color: #8B1A1A;
}

/* ---------- Buttons ---------- */
.btn-primary {
  background: linear-gradient(135deg, #C0392B 0%, #8B1A1A 100%);
  border: none;
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 500;
  font-size: 14px;
  transition: all 0.3s ease;
  box-shadow: 0 2px 6px rgba(192, 57, 43, 0.3);
}

.btn-primary:hover,
.btn-primary:focus {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(192, 57, 43, 0.4);
  background: linear-gradient(135deg, #8B1A1A 0%, #C0392B 100%);
}

.btn-secondary {
  background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
  border: none;
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 500;
  font-size: 14px;
  transition: all 0.3s ease;
  box-shadow: 0 2px 6px rgba(108, 117, 125, 0.3);
}

.btn-secondary:hover,
.btn-secondary:focus {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(108, 117, 125, 0.4);
}

/* ---------- Form Controls ---------- */
.form-control {
  border: 2px solid #e8ecf1;
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 14px;
  transition: border-color 0.3s ease;
}

.form-control:focus {
  border-color: #C0392B;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.1);
}

.form-label {
  font-weight: 500;
  color: #495057;
  margin-bottom: 8px;
}

/* ---------- Select Inputs (selectize) ---------- */
.selectize-input {
  border: 2px solid #e8ecf1 !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  box-shadow: none !important;
}

.selectize-input.focus {
  border-color: #C0392B !important;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.1) !important;
}

.selectize-dropdown .active {
  background-color: rgba(192, 57, 43, 0.1) !important;
  color: #8B1A1A !important;
}

/* ---------- Data Tables ---------- */
.dataTables_wrapper {
  padding: 10px 0;
}

table.dataTable thead th {
  background-color: #8B1A1A;
  color: white;
  font-weight: 500;
  border-bottom: none;
  padding: 12px 16px;
}

table.dataTable thead th:first-child {
  border-radius: 8px 0 0 0;
}

table.dataTable thead th:last-child {
  border-radius: 0 8px 0 0;
}

table.dataTable tbody tr:hover {
  background-color: rgba(192, 57, 43, 0.05) !important;
}

table.dataTable tbody td {
  padding: 10px 16px;
  vertical-align: middle;
}

/* ---------- Sticky DT header (appended 2026-06-20) ---------------------
   ~235 DT calls; only ~17 set scrollY. Tables without scrollY scroll
   inside the card body or the page; their header used to disappear.
   `position: sticky` on `thead th` pins the header to the nearest
   scrolling ancestor (card body / page) so column titles remain visible
   while the engineer scrolls long rows. Header bg already #8B1A1A.

   Notes:
   - DT-with-scrollY mode hides the in-body thead and renders a separate
     header wrapper — this rule no-ops there (no visual change).
   - For `filter = "top"` tables, the filter inputs live in the second
     `<tr>` of `<thead>`. Stick that row just below the header bar so
     column filters stay reachable too.
   - FixedColumns clones the leftmost header into `.DTFC_LeftHeadWrapper`;
     mirror the stickiness so the clone stays aligned. */
table.dataTable thead th {
  position: sticky;
  top: 0;
  z-index: 5;
}
table.dataTable thead tr:nth-child(2) th {
  /* Header row is ~47px tall (12px*2 padding + ~23px content + border). */
  top: 47px;
  z-index: 4;
  background-color: #ffffff;
  color: #1e293b;
}
.DTFC_LeftHeadWrapper thead th,
.DTFC_RightHeadWrapper thead th {
  position: sticky;
  top: 0;
  z-index: 6;
}

/* ---------- Page Header ---------- */
.page-header {
  margin-top: 0;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 2px solid #e8ecf1;
}

.page-header h2 {
  font-weight: 600;
  color: #8B1A1A;
  font-size: 24px;
}

.page-header p {
  color: #6c757d;
  font-size: 14px;
  margin-top: 4px;
}

/* ---------- Value Boxes ---------- */
.bslib-value-box .value-box-showcase .fa,
.bslib-value-box .value-box-showcase .fas {
  font-size: 2rem;
}

/* ---------- Alerts ---------- */
.alert-custom {
  border-radius: 8px;
  border-left: 4px solid #C0392B;
  background-color: #fde8e8;
  color: #8B1A1A;
  padding: 16px;
  margin-bottom: 20px;
}

/* ---------- Progress Bar ---------- */
.progress {
  height: 8px;
  border-radius: 10px;
  background-color: #e9ecef;
  overflow: hidden;
}

.progress-bar {
  border-radius: 10px;
  background: linear-gradient(90deg, #C0392B, #8B1A1A);
  transition: width 0.6s ease;
}

/* ---------- Plotly ---------- */
.plotly {
  border-radius: 8px;
}

/* ---------- Scrollbar ---------- */
::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: #c0c0c0;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #a0a0a0;
}

/* ---------- Footer ---------- */
.app-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 12px 24px;
  background-color: #f8f9fa;
  border-top: 2px solid #e8ecf1;
  color: #6c757d;
  font-size: 13px;
  font-weight: 500;
}

.footer-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.footer-logo {
  border-radius: 50%;
  background-color: #ffffff;
  padding: 2px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  object-fit: contain;
}

/* ========================================================================
   DT FixedColumns + filter="top" — hide the duplicate filter widgets that
   the FixedColumns extension clones into its left-overlay tbody/thead.
   The original (top-of-table) filter row stays clickable; the duplicate
   in the cloned overlay was non-functional and obscured page interaction.
   Targets DT 0.20+ class names (.DTFC_*).
   ======================================================================== */
.DTFC_LeftHeadWrapper thead tr:nth-child(2),
.DTFC_LeftHeadWrapper thead tr.filterRow,
.DTFC_LeftWrapper thead tr:nth-child(2),
.DTFC_RightHeadWrapper thead tr:nth-child(2),
.DTFC_RightWrapper thead tr:nth-child(2) {
  display: none !important;
}

/* ========================================================================
   Modal vs bslib full-screen card — Z-index fix
   ========================================================================
   When a bslib card is expanded via `full_screen = TRUE`, the card mounts
   at a very high z-index (~9999) AND the bslib backdrop overlay sits
   above the body content. Bootstrap modal default is 1055, so any modal
   opened while a card is expanded renders BEHIND the bslib layer.

   Strategy: (1) bump modal/backdrop above any conceivable bslib z-index,
   (2) override Bootstrap's CSS variable too (some bslib versions consume
   it directly), (3) when a modal IS shown, push the bslib full-screen
   card + its overlay below the modal layer as a belt-and-suspenders.
   ======================================================================== */
.modal,
.modal.show,
.modal.fade,
.modal[role="dialog"] {
  --bs-modal-zindex: 2000000;
  z-index: 2000000 !important;
}
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.fade {
  --bs-backdrop-zindex: 1999999;
  z-index: 1999999 !important;
}

/* Belt-and-suspenders: when any modal is currently shown, force bslib
   full-screen card layers below the modal. Uses :has() (Chrome 105+,
   Edge 105+, Electron 25+). The runtime is bundled Electron 33 → safe. */
body:has(.modal.show) .bslib-full-screen,
body:has(.modal.show) .bslib-full-screen-card,
body:has(.modal.show) .bslib-full-screen-overlay,
body:has(.modal.show) [data-full-screen="true"] {
  z-index: 1000 !important;
}

/* ============================================================================
   Basin Map — leaflet built-in layer-control: scroll within when expanded
   ============================================================================
   With ~20 toggles (5 basemaps + 4 PET grids + station markers + flowpath
   layers + uploaded layers + preloaded soil rasters), the expanded
   control overflows tall viewports. Cap its height at 75vh and let it
   scroll vertically inside. Standard leaflet collapse-to-icon behaviour
   is preserved.
============================================================================ */
.leaflet-control-layers-expanded {
  max-height: 75vh;
  overflow-y: auto;
}

/* ============================================================================
   Full-screen card - nav_menu dropdown ("Results v") alignment
   ============================================================================
   Expanding a navset_card_tab makes bslib-card[data-full-screen="true"]
   position:fixed, which forms a new containing block and throws off Popper's
   positioning of the Bootstrap nav dropdown - the menu drifts right and lands
   under the next tab (e.g. under "Reference"). Force the open menu back to
   static placement directly under its toggle. The !important rules override
   Popper's inline transform/inset (which are non-important, so the stylesheet
   wins) and Popper re-applies its inline styles on every reposition, but they
   keep losing to these. Covers every nav_menu in a full-screen card.

   2026-07-01 widening:
   - Removed the .card-header segment from selectors - bslib may hoist the
     nav out of .card-header when it constructs the full-screen container,
     which caused the rule not to match on NESTED navset_card_tabs (the
     "sub-card" case reported by the user). Matching on any .nav .nav-item
     under a fullscreen bslib-card is safe: it only fires when the card is
     actually in the fullscreen state.
   - Added `inset` !important override - Popper writes an inline
     `inset: <T> <R> <B> <L>` shorthand that beats separately-overridden
     top / right / bottom / left due to CSS shorthand-vs-longhand rules
     when Popper re-flushes after our stylesheet.
   - Added parallel selectors for .bslib-full-screen,
     .bslib-full-screen-card, and generic [data-full-screen="true"] so
     older / newer bslib versions all get caught.
============================================================================ */
bslib-card[data-full-screen="true"] .nav .nav-item.dropdown,
.bslib-full-screen              .nav .nav-item.dropdown,
.bslib-full-screen-card         .nav .nav-item.dropdown,
[data-full-screen="true"]       .nav .nav-item.dropdown {
  position: relative !important;
}

bslib-card[data-full-screen="true"] .nav .nav-item.dropdown > .dropdown-menu,
.bslib-full-screen              .nav .nav-item.dropdown > .dropdown-menu,
.bslib-full-screen-card         .nav .nav-item.dropdown > .dropdown-menu,
[data-full-screen="true"]       .nav .nav-item.dropdown > .dropdown-menu {
  position: absolute !important;
  inset: 100% auto auto 0 !important;   /* override Popper's inline shorthand */
  top: 100% !important;
  left: 0 !important;
  right: auto !important;
  bottom: auto !important;
  transform: none !important;
  margin-top: 0.125rem !important;
  z-index: 1080 !important;
}

/* ----------------------------------------------------------------------------
   DataTables "Show N entries" select — duplicate-arrow fix.
   ----------------------------------------------------------------------------
   Bootstrap 5 (which bslib bundles) styles native <select> elements with an
   SVG chevron via `background-image`. DataTables' own length-change <select>
   inside `.dataTables_length` STILL renders the OS-native dropdown arrow,
   so the two overlap and the "50" / "100" text appears partly behind a
   stacked icon. Fix: drop the Bootstrap chevron + force OS-native single
   arrow so we have exactly one indicator. Apply uniformly across every DT
   in the app via the `.dataTables_length select` selector (no per-table
   wiring needed).
*/
.dataTables_length select {
  background-image: none !important;
  padding-right: 0.5rem !important;
  -webkit-appearance: menulist !important;
  -moz-appearance:    menulist !important;
  appearance:         menulist !important;
}

/* ----------------------------------------------------------------------------
   DataTables Buttons (Copy / CSV / Excel) — brand red styling.
   ----------------------------------------------------------------------------
   The DT Buttons extension renders Copy/CSV/Excel as .dt-button with a grey
   gradient by default. Only the Landuse / Soil Classification tables use
   this extension in the app, so a global override is safe. Rules mirror
   .btn-primary (Bootstrap 5) using the theme's primary = #C0392B so the
   buttons match the red "Download Excel" downloadButton() pill used
   elsewhere in the app.
*/
/* Rules revised 2026-07-03 (round 2): first attempt targeted `.dt-button`
   but bslib's Bootstrap-5 DT integration renders each button as
   `<button class="btn btn-secondary buttons-copy buttons-html5">` — NO
   `.dt-button` class in the DOM, so the earlier selectors matched nothing.
   Server-side fix (02g / 02h) passes `className = "btn-primary"` per
   button so bslib emits `class="btn btn-primary ..."` directly (Bootstrap
   handles the red). CSS below is defence-in-depth:
     - `.dt-buttons .btn` catches bs5-wrapped buttons regardless of what
       secondary class DT decided to add
     - `.dt-buttons button.dt-button` catches non-bs5 DT (raw .dt-button
       widget) in case an engineer downgrades DT or removes bslib later
   `background:` shorthand + explicit `background-image: none` kills any
   linear-gradient a downstream DT stylesheet might emit. */
.dataTables_wrapper .dt-buttons > .btn,
.dataTables_wrapper .dt-buttons > button.btn,
.dataTables_wrapper .dt-buttons > a.btn,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button,
.dataTables_wrapper .dt-buttons a.dt-button.dt-button,
.dataTables_wrapper .dt-buttons .dt-button.buttons-html5,
.dataTables_wrapper .dt-buttons .dt-button.buttons-copy,
.dataTables_wrapper .dt-buttons .dt-button.buttons-csv,
.dataTables_wrapper .dt-buttons .dt-button.buttons-excel,
div.dt-buttons > .btn,
div.dt-buttons > button.btn,
div.dt-buttons > button.dt-button.dt-button,
div.dt-buttons > a.dt-button.dt-button {
  background: var(--bs-primary, #C0392B) !important;
  background-color: var(--bs-primary, #C0392B) !important;
  background-image: none !important;
  color: #fff !important;
  border: 1px solid var(--bs-primary, #C0392B) !important;
  border-radius: 0.375rem !important;
  padding: 0.375rem 0.9rem !important;
  font-weight: 400 !important;
  font-size: 0.9rem !important;
  margin-right: 0.35rem !important;
  text-shadow: none !important;
  box-shadow: none !important;
  transition: background-color .15s ease-in-out,
              border-color     .15s ease-in-out,
              box-shadow       .15s ease-in-out;
}
.dataTables_wrapper .dt-buttons > .btn:hover,
.dataTables_wrapper .dt-buttons > .btn:focus,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button:hover,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button:focus,
.dataTables_wrapper .dt-buttons a.dt-button.dt-button:hover,
.dataTables_wrapper .dt-buttons a.dt-button.dt-button:focus,
div.dt-buttons > .btn:hover,
div.dt-buttons > .btn:focus,
div.dt-buttons > button.dt-button.dt-button:hover,
div.dt-buttons > button.dt-button.dt-button:focus,
div.dt-buttons > a.dt-button.dt-button:hover,
div.dt-buttons > a.dt-button.dt-button:focus {
  background: #a5311e !important;
  background-color: #a5311e !important;
  background-image: none !important;
  border-color: #9c2f1d !important;
  color: #fff !important;
  box-shadow: 0 0 0 0.2rem rgba(192, 57, 43, 0.25) !important;
}
.dataTables_wrapper .dt-buttons > .btn:active,
.dataTables_wrapper .dt-buttons > .btn.active,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button:active,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button.active,
.dataTables_wrapper .dt-buttons a.dt-button.dt-button:active,
div.dt-buttons > .btn:active,
div.dt-buttons > button.dt-button.dt-button:active,
div.dt-buttons > a.dt-button.dt-button:active {
  background: #8b1a1a !important;
  background-color: #8b1a1a !important;
  background-image: none !important;
  border-color: #7a1717 !important;
  color: #fff !important;
}
.dataTables_wrapper .dt-buttons button.dt-button.dt-button:disabled,
.dataTables_wrapper .dt-buttons button.dt-button.dt-button.disabled {
  opacity: 0.65 !important;
  cursor: not-allowed !important;
}
/* The inner <span> that DataTables wraps the label in inherits color
   via nothing by default; force white so a nested span (some DT versions
   wrap the label) doesn't stay dark against the red bg. */
.dataTables_wrapper .dt-buttons .dt-button > span,
div.dt-buttons > .dt-button > span {
  color: #fff !important;
}

/* ==========================================================================
   Reach > Flow Direction sub-tab — sticky header
   ==========================================================================
   VERIFIED by playwright DOM inspection 2026-07-05:
     - DT auto-generates the wrapper id as `DataTables_Table_0_wrapper`
       (or `DataTables_Table_N_wrapper` when multiple DTs are on the page),
       NOT `{outputId}_wrapper`. A selector of `#reach_dir_table_wrapper`
       matches NOTHING and is a silent no-op.
     - bslib page_navbar layouts have NO document/window scroll.
       Scrolling happens inside `.card-body` (overflow: auto). DT's own
       `scrollY` internal scroll container only helps within the DT
       viewport — it does nothing when the engineer scrolls the tab body.

   Fix: scope by DT's OUTER widget id (`#reach_dir_table`), which is the
   Shiny outputId and thus stable. Apply `position: sticky; top: 0` on
   every `<th>` inside the wrapper so headers pin to the top of the
   nearest scroll ancestor (card-body). Opaque bg so row text doesn't
   ghost through as rows scroll under.
   ========================================================================== */
/* ==========================================================================
   Reach > Flow Direction sub-tab — sticky-header fix
   ==========================================================================
   VERIFIED root cause via playwright DOM/CSS cascade inspection (2026-07-05):
   DataTables adds classes `.sorting`, `.sorting_asc`, `.sorting_desc` to
   every SORTABLE header cell. DataTables' built-in CSS has:

     table.dataTable thead > tr > th.sorting {
       position: relative;         // needed by DT to absolute-position the
       ...                         // sort-arrow ::after pseudo-element
     }

   This rule has specificity 0-2-4 (2 classes .dataTable + .sorting;
   4 elements). The global sticky rule at line ~344 is:

     table.dataTable thead th { position: sticky; ... }   // 0-1-3

   0-2-4 beats 0-1-3, so `.sorting` cells stay `relative` and DO NOT pin.
   The Reverse? column is `orderable = FALSE` in server/02f_reach.R, so
   it never gets `.sorting`, so the global sticky rule wins — that's why
   only Reverse? was pinning in the previous state.

   Fix: scope by the widget id `#reach_dir_table` (specificity 1-2-3 =
   123) which trivially beats the sorting rule's 24. Applies sticky to
   ALL <th> in the Flow Direction DT regardless of sortability. Does NOT
   set background-color — the global rule at line 304 already paints
   #8B1A1A red, and we want to inherit that (matches Overall > Summary
   and every other DT in the app). */
#reach_dir_table .dataTables_wrapper table.dataTable thead th {
  position: sticky;
  top: 0;
  z-index: 5;
}
/* Border-collapse: separate is still needed as a safety net for the
   flat-table case (no scrollY). Bootstrap's default `collapse` blocks
   sticky in some browsers even when specificity is right. */
#reach_dir_table .dataTables_wrapper table.dataTable {
  border-collapse: separate;
  border-spacing: 0;
}

/* MC User Defined / Manning's n L / Manning's n R — persistent
   selected-row highlight after row click. Toggled by DOM class in the
   .mc_dt_reach_interactive_callback JS. Resets on DT re-render (accepted). */
#mc_user_defined_table tbody tr.mc-row-selected,
#mc_left_manning_table tbody tr.mc-row-selected,
#mc_right_manning_table tbody tr.mc-row-selected {
  background-color: #fff3cd !important;
}
#mc_user_defined_table tbody tr.mc-row-selected td,
#mc_left_manning_table tbody tr.mc-row-selected td,
#mc_right_manning_table tbody tr.mc-row-selected td {
  background-color: #fff3cd !important;
}

