/*
 * =============================================================
 * icori-responsive.css - Responsive overrides for icori.css
 * =============================================================
 * Breakpoints:
 *   @media (max-width: 1024px)  - Tablet
 *   @media (max-width: 875px)   - Mobile mode (nav collapses to hamburger;
 *                                 matches xfact-mds.css nav breakpoint)
 *   @media (max-width: 480px)   - Small mobile
 *
 * EXCEPTION: the Step Indicator block below stays at max-width:768px on
 * purpose - it counters a vendor rule pinned to 768px; see its own note.
 *
 * Contains ONLY overrides - rules that change at a breakpoint.
 * Load AFTER icori.css.
 * =============================================================
 */


/* =============================================================
   Buttons
   ============================================================= */

/* Mobile nav: the cart button follows the nav <ul> in DOM order, so without
   ordering it wraps below the item list. Reorder the flex children
   (hamburger | cart | list) to keep the cart on the toggle row.

   .icori-cart-btn-wrap must be listed alongside .icori-cart-btn: the tooltip
   work wrapped the button in a positioned <span>, which made the WRAPPER the
   flex child of .mds-nav__inner. An unordered child defaults to order:0, so
   it sorted ahead of the order:1 toggle, and its margin-left:auto then shoved
   the toggle right along with it - the Menu label ended up on the right-hand
   side of the bar. Both selectors are kept so either shape orders correctly.

   The main nav's list no longer takes part: it is a viewport-pinned overlay
   panel from 875px down (see Section 49 in xfact-mds.css), so it is out of
   flow. The in-page .xf-nav sub-menu bars still open as an in-flow accordion
   and still need the ordering. */
@media (max-width: 875px) {
  .mds-nav__hamburger,
  .xf-nav__hamburger   { order: 1; }
  .icori-cart-btn,
  .icori-cart-btn-wrap { order: 2; }
  .xf-nav__list        { order: 3; }

  /* Smaller/tighter than the desktop .mds-btn--md sizing, to fit the
     pinned mobile nav bar's toggle row. 40px, not the min-height:34px
     this used to fall out to from padding alone - the homepage's
     sticky action-bar icon buttons sit at 40px on mobile too (see
     .results-table-toolbar__actions .icori-action-link in icori-
     responsive.css), and 34px read visibly smaller beside them. */
  .icori-cart-btn {
    padding: var(--space-0) var(--space-4);
    height: 40px;
    font-size: var(--type-size-base);
    font-weight: 500;
  }
}


/* =============================================================
   Account Type Questions
   ============================================================= */

@media (max-width: 480px) {
  .icori-account-type-question {
    padding-top: 1rem;
  }

  .icori-account-type-question legend {
    font-size: var(--type-size-sm);
  }
}


/* =============================================================
   Step Indicator
   ============================================================= */

/* The app only ever renders the --desktop stepper variant; it never emits the
   vendor --tablet / --mobile markup (a different __bar-track / __bar-segment /
   __current / __next structure). The vendor breakpoint rules (xfact-mds.css
   Section 37) hide --desktop below 769px and rely on those other variants
   appearing - so below 769px the stepper vanished entirely.

   Rather than shrink the horizontal desktop row (which cramps or clips the step
   labels on a phone), reflow the SAME markup into a vertical list at <=768px:
   each step becomes a full-width row - a short colored tick + the full step
   label - so every step name stays visible and nothing runs off-screen.
   Equal specificity to the vendor display:none + later source order wins across
   the whole <=768px range.

   NOTE: this block intentionally stays at <=768px, NOT the app-wide 767|768
   boundary the rest of this file uses. The vendor hides --desktop in
   (min-width:481px) and (max-width:768px), so our reflow MUST span the full
   vendor-hide band up to 768px inclusive. Dropping it to <=767 would leave the
   stepper hidden with no replacement at exactly 768px (it would vanish). */
@media (max-width: 768px) {
  /* On mobile the Cancel / Sign-out button pins top-right of the stepper
     area.  Right padding on the stepper reserves space so labels wrap
     instead of colliding with the button — works down to 320px. */
  .icori-stepper-area { position: relative; }
  .icori-cancel-row   {
    position: absolute;
    top: 0;
    right: 0;
    margin: 0;
    z-index: 1;
  }
  .mds-step-indicator,
  .mds-step-indicator--desktop {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-4, 1rem);
    padding-right: 5.5rem; /* reserve room for Cancel / Sign-out button */
  }

  /* Each step: horizontal row of [tick] [label], natural height, no min-width
     floor (the 120px floor is only meaningful for the horizontal layout). */
  .mds-step-indicator__step {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
    padding-right: 0;
  }

  /* The progress bar becomes a short vertical tick beside the label. */
  .mds-step-indicator__bar {
    flex: 0 0 6px;
    width: 6px;
    height: 1.5rem;
    border-radius: var(--radius-sm, 3px);
  }

  /* Full label - wraps into the narrower space left by the cancel button. */
  .mds-step-indicator__label {
    max-width: none;
    overflow: visible;
    white-space: normal;
  }

  /* Tighten stepper top margin on mobile */
  .mds-step-indicator {
    margin-top: var(--space-2);
  }

  /* Button group fills full width, buttons split 50/50.
     Override vendor stacking (flex-direction:column at <=479px)
     so the pair stays side-by-side until it truly can't fit. */
  .mds-btn-group--fixed {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    width: 100%;
  }
  .mds-btn-group--fixed > .mds-btn,
  .mds-btn-group--fixed > form {
    flex: 1 1 0;
    min-width: 0;
  }
  .mds-btn-group--fixed > form > .mds-btn {
    width: 100%;
  }
  #continueBtn {
    width: auto;
  }
}


/* =============================================================
   Button Group (.xf-btn-group)
   ============================================================= */

/* xfact-custom-style.css gives .xf-btn-group `display:flex; width:fit-content`
   with NO wrap, so a two-button row (e.g. "Send consent request" + "Cancel")
   runs off the right edge on a phone.

   Two-state design (no intermediate equal-width tier): buttons stay content-
   sized in a row on desktop, then flip to a full-width vertical stack at
   <=767px - the exact breakpoint the app switches into mobile mode (the
   hamburger nav flips at max-width:767 in xfact-mds.css). Stacking (not an
   equal-width row) at this breakpoint makes overflow structurally impossible
   regardless of label length, since each button owns its own full-width line.
   The only band left with a horizontal row is >=768px, where the widest real
   pair ("Submit registration" + "Cancel registration", ~416px content-sized)
   is nowhere near the viewport width. */
@media (max-width: 767px) {
  .xf-btn-group {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  /* Buttons stack full-width. Includes the form-wrapped "Send email again"
     button in the DUPLICATE result: icori.css sets `.xf-btn-group > form`
     to display:contents, so its button is a direct flex child here and this
     descendant rule (plus the column align-items:stretch above) fills it. */
  .xf-btn-group .mds-btn {
    width: 100%;
  }
}


/* =============================================================
   Cart Panel Accordion
   ============================================================= */

@media (max-width: 767px) {
  /* Tighter gap between details and the action buttons on mobile (the base is
     already a vertical stack). */
  .icori-cart-item {
    gap: var(--space-4);
  }

  /* 3-col detail grid → 2-col on tablet */
  .icori-cart-item__details {
    grid-template-columns: 1fr 1fr;
  }

  /* Actions flip from the desktop right-aligned row to a full-width stack,
     matching the rest of the mobile buttons. A row tier was avoided because
     Remove is wrapped in a <form> - as the flex child it wouldn't take flex:1,
     so a row came out lopsided (wide Edit, natural-width Remove). Stacked with
     width:100% fills both, form wrapper and all. */
  .icori-cart-item__actions {
    flex-direction: column;
  }
  .icori-cart-item__actions .mds-btn {
    width: 100%;
  }

  .icori-cart-panel__body {
    padding: var(--space-3) var(--space-4);
  }

  /* Continue to checkout goes full-width, like the other mobile buttons. */
  .icori-cart-checkout-btn {
    width: 100%;
    text-align: center;
  }
}

@media (max-width: 480px) {
  /* 2-col detail grid → single column on small mobile */
  .icori-cart-item__details {
    grid-template-columns: 1fr;
  }

  .icori-cart-panel__header {
    padding: var(--space-2) var(--space-3);
    gap:     var(--space-2);
  }
}


/* =============================================================
   Cart Total Bar
   ============================================================= */

@media (max-width: 480px) {
  .icori-cart-total {
    flex-direction: column;
    align-items: flex-end;
    gap: 0.25rem;
    padding: var(--space-2) var(--space-3);
  }
}


/* =============================================================
   Verify Order - Order Meta Grid
   ============================================================= */

/* 3-col → 2-col on tablet */
@media (max-width: 1024px) {
  .icori-order-meta {
    grid-template-columns: 1fr 1fr;
  }
}

/* 2-col → single column on small mobile */
@media (max-width: 480px) {
  .icori-order-meta {
    grid-template-columns: 1fr;
  }
}


/* =============================================================
   Inline Grid Overrides
   Covers both literal (1fr 1fr 1fr) and repeat() forms used in
   templates, plus asymmetric multi-col layouts (3fr 2fr, 2fr 1fr)
   ============================================================= */

/* --- 2-col asymmetric (welcome page hero, sidebars) ---------- */
@media (max-width: 767px) {
  [style*="grid-template-columns:3fr 2fr"],
  [style*="grid-template-columns: 3fr 2fr"],
  [style*="grid-template-columns:2fr 1fr"],
  [style*="grid-template-columns: 2fr 1fr"] {
    grid-template-columns: 1fr !important;
  }

  /* Welcome page only (3fr 2fr, not the 2fr 1fr sidebars): the
     register/log-in column (2nd child) reads before the introductory
     text on mobile, since that's the action a mobile visitor is most
     likely there for. Desktop keeps intro-left/login-right as-is -
     `order` only ever affects visual order, never DOM/tab order, so
     screen-reader and keyboard navigation still hit the intro text
     first regardless of viewport. */
  [style*="grid-template-columns:3fr 2fr"] > div:nth-child(2),
  [style*="grid-template-columns: 3fr 2fr"] > div:nth-child(2) {
    order: -1;
  }
}

/* --- 3-col → 2-col on tablet --------------------------------- */
@media (max-width: 767px) {
  [style*="grid-template-columns:1fr 1fr 1fr"],
  [style*="grid-template-columns: 1fr 1fr 1fr"],
  [style*="grid-template-columns:repeat(3,1fr)"],
  [style*="grid-template-columns: repeat(3,1fr)"],
  [style*="grid-template-columns:repeat(3, 1fr)"],
  [style*="grid-template-columns: repeat(3, 1fr)"] {
    grid-template-columns: 1fr 1fr !important;
  }

  [style*="grid-template-columns:1fr 1fr"],
  [style*="grid-template-columns: 1fr 1fr"],
  [style*="grid-template-columns:repeat(2,1fr)"],
  [style*="grid-template-columns: repeat(2,1fr)"],
  [style*="grid-template-columns:repeat(2, 1fr)"],
  [style*="grid-template-columns: repeat(2, 1fr)"] {
    grid-template-columns: 1fr !important;
  }
}

/* --- everything → single column on small mobile -------------- */
@media (max-width: 480px) {
  [style*="grid-template-columns:1fr 1fr 1fr"],
  [style*="grid-template-columns: 1fr 1fr 1fr"],
  [style*="grid-template-columns:1fr 1fr"],
  [style*="grid-template-columns: 1fr 1fr"],
  [style*="grid-template-columns:repeat(3,1fr)"],
  [style*="grid-template-columns: repeat(3,1fr)"],
  [style*="grid-template-columns:repeat(3, 1fr)"],
  [style*="grid-template-columns: repeat(3, 1fr)"],
  [style*="grid-template-columns:repeat(2,1fr)"],
  [style*="grid-template-columns: repeat(2,1fr)"],
  [style*="grid-template-columns:repeat(2, 1fr)"],
  [style*="grid-template-columns: repeat(2, 1fr)"] {
    grid-template-columns: 1fr !important;
  }

}

/* --- 6-col registration address grid → single column on mobile ----------- */
/* org-contact and rep-address sections use repeat(6,1fr) with span-3 flex
   sub-rows for Country+State and City/Town+Zip pairing. */
@media (max-width: 767px) {
  [style*="grid-template-columns:repeat(6,1fr)"] {
    grid-template-columns: 1fr !important;
  }
  /* Span overrides on direct children and fieldset[display:contents] children
     would auto-create implicit columns if left as span N on a 1-col grid. */
  [style*="grid-template-columns:repeat(6,1fr)"] > *,
  [style*="grid-template-columns:repeat(6,1fr)"] > fieldset > * {
    grid-column: 1 / -1 !important;
  }
  /* Stack the paired Country+State and City/Town+Zip flex rows vertically. */
  [style*="grid-column:span 3"][style*="display:flex"],
  [style*="grid-column: span 3"][style*="display:flex"] {
    flex-direction: column;
  }
}



/* =============================================================
   Results page (≤767px)
   ============================================================= */
@media (max-width: 767px) {
  .mds-accordion {
    margin-bottom: var(--space-4);
  }

  /* Filter panel must sit above the sticky toolbar (--z-sticky: 1020) so
     its dropdowns open in front of it. --z-dropdown (1000) alone is not
     enough; raising the filter's stacking context covers both custom
     .p-select overlays and native <select> popups in Chromium WebView. */
  .mds-filters {
    position: relative;
    z-index: calc(var(--z-sticky) + 10);  /* 1030 */
  }

  /* The mobile nav panel and scrim are position:fixed and escape the nav's
     own stacking context, landing in the root at z-dropdown+1 (1001). Our
     filter raised to 1030 sits above them. Override to --z-modal-bg / --z-modal
     (1040/1050) so the nav panel always paints over the filter when open. */
  .mds-nav__scrim  { z-index: var(--z-modal-bg); }   /* 1040 */
  .mds-nav__list   { z-index: var(--z-modal);    }   /* 1050 */

  /* The sticky nav bar sits at calc(--z-sticky + 1) = 1021, below the filter's
     1030. Raise it so the filter's stacking context can't paint over the bar.
     The mobile panel (1050) and scrim (1040) still sit above it when open. */
  .mds-nav { z-index: calc(var(--z-sticky) + 12); }  /* 1032 */

  /* Title bar wraps so the action buttons drop below the title instead of
     being crushed beside it. The buttons then stack full-width, matching the
     request form action buttons (.icori-request-actions). */
  .xf-page-title-bar {
    flex-wrap: wrap;
  }
  .xf-page-title-bar__actions {
    width: 100%;
    align-self: auto;
    margin-top: var(--space-2);
    gap: var(--space-2);
    flex-direction: column;
    align-items: stretch;
  }
  .xf-page-title-bar__action {
    height: auto;
    border-radius: var(--radius-md);
    width: 100%;
    text-align: center;
  }
  .xf-page-title-bar__action + .xf-page-title-bar__action {
    margin-left: 0; /* spacing handled by the container gap */
  }

  /* Filter & sort fields: 2 columns on mobile (icori.css drops from 3→1 at
     640px which is too narrow; force 2 cols across the 501–767px band).
     The ≤500px override further down drops to 1 column. */
  .mds-tablefilters {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The Filters & sort panel is visible on all viewports (see icori.css); no
     reveal needed here. Its Apply filters button goes full-width to match the
     title-bar action buttons. */
  .results-controls__actions {
    flex-direction: column;
    justify-content: stretch;
  }
  .results-controls__actions .mds-btn {
    width: 100%;
    text-align: center;
  }

  /* The "Expand all / Collapse all" toggle stacks full-width too, matching the
     title-bar and Apply-filters action buttons on mobile. */
  .results-detail-toolbar {
    justify-content: stretch;
  }
  .results-detail-toolbar .mds-btn {
    width: 100%;
    text-align: center;
  }

}

/* Filter fields: single column at ≤500px - must come after the ≤767px block
   above (which sets 2 columns) so this later rule wins at narrow viewports. */
@media (max-width: 500px) {
  .mds-tablefilters {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* =============================================================
   Results table - squeeze tier (768px–1035px)
   Tighter cell padding buys room for the Download button before
   card mode takes over at ≤1035px.
   ============================================================= */
@media (min-width: 768px) and (max-width: 1035px) {
  #results-table thead th,
  #results-table tbody td {
    padding: 0 0.3rem;
  }
  #results-table .custom-datatable__sort-header {
    padding: 0 0.3rem;
  }
  #results-table {
    --col-status: 10%;
    --col-details: 10%;
    --col-actions: 13%;
  }
}


/* =============================================================
   Results table - card mode (≤1035px)
   Cuts over earlier than the vendor's 480px card-mobile breakpoint
   to match the home-layout. Two cards per row down to ~480px,
   then one per row below that.
   ============================================================= */
@media (max-width: 1035px) {
  /* Hide the action toolbar when the table shows its empty state - the toolbar's
     select/download/expand actions are meaningless with no rows. Both pages already
     remove the toolbar server-side via th:if when results is empty; this CSS provides
     a client-side safety net for any case where the empty td is in the DOM but the
     toolbar is still present. */
  body:has(#homepage-requests-table .xf-table__empty) .results-table-toolbar,
  body:has(#results-table .xf-table__empty) .results-table-toolbar {
    display: none;
  }

  /* Hide the table header - labels come from data-label instead.
     Scoped to results/homepage tables; other tables (account, etc.) stay in
     table layout until the 767px breakpoint handles them. */
  #results-table.custom-datatable--card-mobile thead,
  #homepage-requests-table.custom-datatable--card-mobile thead { display: none; }

  /* Reset table-layout:fixed and column width vars - card mode doesn't use columns. */
  #results-table {
    table-layout: auto;
    min-width: 0;
    width: 100%;
  }

  /* Remove the table wrapper border/radius - each card has its own.
     Scoped to results/homepage tables only. */
  .custom-datatable-wrapper:has(#results-table),
  .custom-datatable-wrapper:has(#homepage-requests-table) {
    border: none;
    border-radius: 0;
  }

  /* ---- Card grid layout: 2-up down to 480px ---- */
  #results-table.custom-datatable--card-mobile tbody,
  #homepage-requests-table.custom-datatable--card-mobile tbody {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 0 var(--space-6);
  }
  /* Empty-state row spans both columns. Exclude .results-row / .results-detail:
     JS moves td.results-detail-cell[colspan] into every results-row, so an
     unguarded :has(>td[colspan]) would make every card span full width. */
  #results-table.custom-datatable--card-mobile tbody tr:not(.results-row):not(.results-detail):has(> td[colspan]),
  #homepage-requests-table.custom-datatable--card-mobile tbody tr:not(.results-row):not(.results-detail):has(> td[colspan]) {
    grid-column: 1 / -1;
  }
  /* Results table empty-state: add the same card border that .xf-table tbody tr
     gets from xfact-custom-style.css at ≤767px (which the home table inherits).
     The results table uses custom-datatable, not xf-table, so it doesn't get
     that generic rule - add the card box here so it matches home at ≤1035px. */
  #results-table.custom-datatable--card-mobile tbody tr:not(.results-row):not(.results-detail):has(> td[colspan]) {
    border: 1px solid #dcdcdc;
    border-radius: 8px;
    background-color: #ffffff;
    overflow: hidden;
  }

  /* Reset vendor tbody tr border for non-card rows; .results-row cards keep
     their own border: 1px solid from the rule below (if we cleared it here at
     higher ID specificity, every card would lose its bottom edge). */
  #results-table.custom-datatable--card-mobile tbody tr:not(.results-row),
  #homepage-requests-table.custom-datatable--card-mobile tbody tr:not(.results-row) {
    border-bottom: none;
  }

  .custom-datatable--card-mobile tbody tr.results-row {
    display: flex;
    flex-wrap: wrap;
    height: auto;
    margin-bottom: var(--space-6);
    padding: 0 var(--space-4);
    background-color: #ffffff;
    border: 1px solid #dcdcdc;
    border-radius: 8px;
    overflow: hidden;
  }

  /* Restore bottom border on last card - desktop strips it but cards need it. */
  #results-table.custom-datatable--card-mobile tbody tr.results-row:has(+ tr.results-detail:last-child) {
    border-bottom: 1px solid #dcdcdc;
  }

  /* Kill desktop zebra - each card is always white */
  #results-table.custom-datatable--card-mobile tbody tr:nth-child(4n+1),
  #results-table.custom-datatable--card-mobile tbody tr:nth-child(4n+2),
  #results-table.custom-datatable--card-mobile tbody tr:nth-child(4n+3),
  #results-table.custom-datatable--card-mobile tbody tr:nth-child(4n)   { background-color: #ffffff; }

  /* ID-scoped to beat .custom-datatable tbody td (icori.css) which sets
     height:68px and padding:0 1rem on the desktop table. */
  #results-table.custom-datatable--card-mobile tbody td {
    display: flex;
    flex: 0 0 100%;
    align-items: center;
    justify-content: space-between;
    height: auto;
    width: 100%;
    font-size: var(--type-size-base);
    font-weight: normal;
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-gray-200);
    border-top: none;
    background-color: transparent;
    text-align: right;
    /* Long unbreakable values wrap inside the card, not past its edge. */
    overflow-wrap: anywhere;
  }

  #results-table.custom-datatable--card-mobile tbody td:last-child,
  #results-table.custom-datatable--card-mobile tbody td[colspan],
  #homepage-requests-table.custom-datatable--card-mobile tbody td:last-child,
  #homepage-requests-table.custom-datatable--card-mobile tbody td[colspan] {
    border-bottom: none;
  }

  #results-table.custom-datatable--card-mobile tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--type-size-base);
    font-weight: var(--font-weight-semibold, 600);
    color: inherit;
    text-transform: none;
    letter-spacing: normal;
    text-align: left;
    margin-right: var(--space-2);
  }
  /* Empty-state cell only - scoped to .xf-table__empty to avoid matching
     td.results-detail-cell which also carries colspan="7". Hitting that cell
     would force display:block (breaking the toggle) and border-bottom:none
     (removing the rule between the detail content and the Actions row). */
  #results-table.custom-datatable--card-mobile tbody td.xf-table__empty {
    display: block !important;
    text-align: center !important;
    justify-content: center !important;
    font-size: var(--type-size-base) !important;
    font-weight: normal !important;
    padding: 1.5rem 0 !important;
    border-bottom: none !important;
  }
  #results-table.custom-datatable--card-mobile tbody td.xf-table__empty::before {
    content: none !important;
  }

  /* ---- Expandable rows in card view ----
     [No./Date/Subject/Status](0) → Toggle(5)+Result(6) → Detail(7) → Actions(8). */
  #results-table.custom-datatable--card-mobile tbody td.results-row__toggle {
    order: 5;
    flex: 1 1 50%;
    min-width: 10rem;
    width: auto;
    white-space: normal;
    justify-content: flex-start;
    padding-right: var(--space-3);
  }
  #results-table.custom-datatable--card-mobile tbody td.results-row__toggle::before { content: none; }
  #results-table.custom-datatable--card-mobile .results-expander { width: 100%; }

  #results-table.custom-datatable--card-mobile tbody td[data-label="Result"] {
    order: 6;
    flex: 1 1 50%;
    min-width: 6rem;
  }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Result"]:has(.icori-result-badge)::before { content: none; }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Result"] .icori-result-badge { width: 100%; }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Result"]:not(:has(.icori-result-badge)) { justify-content: flex-end; }

  /* Result / Actions labels are secondary to their visual content (badge, button)
     so they render at normal weight rather than semibold. */
  #results-table.custom-datatable--card-mobile tbody td[data-label="Result"]::before,
  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"]::before {
    font-weight: normal;
  }

  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"] {
    order: 8;
    align-items: center;
    border-bottom: none;
    margin-top: 0;
    padding: var(--space-3) 0;
    border-top: none;
  }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"]:not(:has(.mds-btn--fill-accent)) { justify-content: flex-start; }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"]:has(.mds-btn--fill-accent) { padding-top: var(--space-3); }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"]:has(.mds-btn--fill-accent)::before { content: none; }
  #results-table.custom-datatable--card-mobile tbody td[data-label="Actions"] .mds-btn--fill-accent {
    width: 100%;
    justify-content: center;
    font-size: var(--type-size-base);
    padding: var(--space-3) var(--space-4);
  }

  /* No./checkbox: header band */
  #results-table.custom-datatable--card-mobile tbody td[data-label="No."] {
    flex: 0 0 calc(100% + (var(--space-4) * 2));
    margin: 0 calc(var(--space-4) * -1);
    padding: var(--space-3) var(--space-4);
    background-color: var(--color-berkshires-green-100) !important;
    border-bottom: 1px solid var(--color-gray-200);
    justify-content: flex-start;
    gap: var(--space-2);
  }
  #results-table.custom-datatable--card-mobile tbody td[data-label="No."]::before {
    content: attr(data-label);
    order: 1;
  }
  #results-table.custom-datatable--card-mobile tbody td[data-label="No."] .xf-table-check { order: 0; }
  #results-table.custom-datatable--card-mobile tbody td[data-label="No."] span               { order: 2; }

  /* JS moves td.results-detail-cell from tr.results-detail into tr.results-row,
     leaving tr.results-detail empty - hide it unconditionally. */
  .custom-datatable--card-mobile tbody tr.results-detail { display: none !important; }

  .custom-datatable--card-mobile tbody tr.results-row > td.results-detail-cell {
    display: none !important;
    order: 7;
    flex: 0 0 100%;
  }

  .custom-datatable--card-mobile tbody tr.results-row.is-expanded > td.results-detail-cell {
    display: block !important;
    border-bottom: 1px solid var(--color-gray-200);
  }
  .custom-datatable--card-mobile td.results-detail-cell::before { content: none !important; }

  /* ── CONSENT HISTORY - mobile card layout ──────────────────────────────
     Mirrors the results-row card treatment but simpler: no expand/detail rows,
     no checkboxes. Scoped to .consent-history-table so desktop and other pages
     are unaffected.
     ─────────────────────────────────────────────────────────────────────── */

  /* Hide the header - labels come from data-label instead. Consent's card
     treatment starts at this 1035px breakpoint, but the generic
     .custom-datatable--card-mobile thead { display: none } (mds-responsive.css)
     only fires at 767px. Without this, thead stays visible in the 768-1035px
     band and populated cards carry a stray header row above them.
     Exception: an EMPTY table (:has(tbody td[colspan])) has no cards - it falls
     through to the generic empty-state behavior (see empty-state note below), so
     in this 768-1035px band it stays a plain desktop table and must keep its
     header. (Below 767px the generic thead-hide takes over and it becomes a
     bordered card, matching the users table.) */
  .consent-history-table.custom-datatable--card-mobile:not(:has(tbody td[colspan])) thead { display: none; }

  /* Card shape (non-empty tables only; empty tables use the generic empty-state
     behavior - see the empty-state note below). */
  .consent-history-table.custom-datatable--card-mobile:not(:has(tbody td[colspan])) tbody tr {
    display: flex;
    flex-wrap: wrap;
    height: auto;
    margin-bottom: var(--space-6);
    padding: 0 var(--space-4);
    background-color: #ffffff;
    border: 1px solid #dcdcdc;
    border-radius: 8px;
    overflow: hidden;
  }

  /* Empty-state: an empty table has no cards to show, so it does NOT get consent's
     card treatment at all - it falls through to the app-wide generic empty-state
     behavior instead (see the .custom-datatable--card-mobile rules below), which
     is exactly how the users/manage-org tables render "No records":
       - 768-1035px: a plain desktop table (header visible, message spanning all
         columns, centred) inside the bordered wrapper;
       - <=767px: a bordered white card with the centred message.
     That is why the card rules on tbody tr / td / td::before are scoped with
     :not(:has(tbody td[colspan])) - they must skip empty tables. */

  /* Cell layout - override desktop .custom-datatable tbody td height/padding */
  .consent-history-table.custom-datatable--card-mobile:not(:has(tbody td[colspan])) tbody td {
    display: flex;
    flex: 0 0 100%;
    align-items: center;
    justify-content: space-between;
    height: auto;
    width: 100%;
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-gray-200);
    border-top: none;
    background-color: transparent;
    text-align: right;
    min-width: 0;
    /* Long unbreakable values (e.g. an org email address) wrap inside the
       card instead of overflowing its right edge. */
    overflow-wrap: anywhere;
  }

  /* Field label before each value (non-empty tables only) */
  .consent-history-table.custom-datatable--card-mobile:not(:has(tbody td[colspan])) tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-weight: var(--font-weight-semibold, 600);
    text-align: left;
    margin-right: var(--space-2);
    white-space: nowrap;
  }

  /* Last cell - no bottom divider */
  .consent-history-table.custom-datatable--card-mobile tbody td:last-child {
    border-bottom: none;
  }

  /* No. cell: full-bleed header band - matches results-row No./checkbox band */
  .consent-history-table.custom-datatable--card-mobile tbody td[data-label="No."] {
    flex: 0 0 calc(100% + (var(--space-4) * 2));
    margin: 0 calc(var(--space-4) * -1);
    padding: var(--space-3) var(--space-4);
    background-color: var(--color-berkshires-green-100) !important;
    border-bottom: 1px solid var(--color-gray-200);
    justify-content: flex-start;
    font-weight: var(--font-weight-semibold, 600);
  }
  .consent-history-table.custom-datatable--card-mobile tbody td[data-label="No."]::before {
    content: attr(data-label);
    margin-right: var(--space-2);
  }

  /* Status badge - release desktop min-width so it doesn't overflow the card */
  .consent-history-table.custom-datatable--card-mobile .mds-badge {
    min-width: 0;
  }

  /* Actions cell - release desktop column width; button spans full width */
  .consent-history-table.custom-datatable--card-mobile tbody td[data-label="Actions"] {
    width: auto;
    min-width: 0;
    justify-content: flex-start;
  }
  .consent-history-table.custom-datatable--card-mobile tbody td[data-label="Actions"] .mds-btn {
    min-width: 0;
    width: 100%;
    justify-content: center;
  }

  #results-table .results-detail__grid {
    grid-template-columns: 1fr;
    gap: 0;
    padding: 0;
  }
  #results-table .results-detail__grid > [aria-hidden="true"] {
    display: none;
  }
  #results-table .results-detail__item {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-4);
    min-width: 0;
    padding: var(--space-1) 0;
  }
  .custom-datatable--card-mobile .results-detail__label { flex-shrink: 0; }
  .custom-datatable--card-mobile .results-detail__value { text-align: right; }

  /* Action cells: neutralize vendor td:last-child overrides */
  .custom-datatable--card-mobile tbody td[data-label="Actions"]:has(> *),
  .custom-datatable--card-mobile tbody td[data-label="Action"]:has(> *) {
    justify-content: space-between;
    padding-top: var(--space-1);
    margin-top: 0;
    border-top: none;
  }

  .custom-datatable tbody td .mds-icon-btn--sm {
    width: 28px;
    height: 28px;
    padding: 6px;
  }
}

/* One card per row below 851px - badges start wrapping in a half-width card
   around this width (matches home-layout cutover).
   #results-table is repeated here to match the specificity of the 1fr 1fr rule
   above (which uses the ID), so this override wins at the narrower breakpoint. */
@media (max-width: 851px) {
  .custom-datatable--card-mobile tbody,
  #results-table.custom-datatable--card-mobile tbody {
    grid-template-columns: 1fr;
  }
}



/* =============================================================
   Homepage table - MDS retheme, squeeze tier 1 (1126px-1279px)
   Same fixed --col-* percentage columns as desktop (icori.css), just
   tighter cell padding to buy the Actions column enough room for the
   Download button before it starts crowding the cell edge again - see
   squeeze tier 2 below for the next step down.

   .custom-datatable__sort-header carries its own 1rem padding (icori.css)
   that wins over the plain th padding above - a sortable header's th has
   its own padding zeroed out precisely so the header button/link can fill
   the cell edge-to-edge (see icori.css's own comment on that rule), so
   the sort-header's padding is the one actually visible and needs its own
   matching override here, or the sortable headers (Date/time, Subject,
   Status, Result) stay at full 1rem padding while every other cell - and
   the non-sortable headers - tightens up around them. */
@media (min-width: 1126px) and (max-width: 1279px) {
  .xf-table--mds thead th,
  .xf-table--mds tbody td {
    padding: 0 0.5rem;
  }
  .xf-table--mds .custom-datatable__sort-header {
    padding: 0 0.5rem;
  }
}

/* =============================================================
   Homepage table - MDS retheme, squeeze tier 2 (1036px-1125px)
   Tier 1's 0.5rem padding starts crowding the Download button again
   around 1125px. Two more levers here, stacked: tighter padding still
   (0.3rem, including the sort-header's own padding - see tier 1's note
   above), plus narrowing Status and Details - both have more room than
   they need (a short word; a button that already has its own 10rem
   min-width floor) - and handing some of the freed space to Actions
   (12% -> 13%), the one column that's actually tight. Together these
   hold the line down to ~1035px, where card mode takes over.

   NOTE: these seven --col-* values sum to 92%, not 100% - Status and
   Details free 9% (5% + 4%) and only 1% of that goes to Actions here.
   icori.css's own comment on the --col-* block calls out a 100% sum as
   load-bearing (table-layout:fixed resolves both the header's column
   widths AND results-detail__grid's grid-template-columns against it,
   so a mismatch was the exact cause of a past alignment bug) - flagging
   in case the remaining 8% was meant to land somewhere specific rather
   than fall out of the sum. */
@media (min-width: 1036px) and (max-width: 1125px) {
  .xf-table-wrapper.xf-table--mds {
    --col-status: 10%;
    --col-details: 10%;
    --col-actions: 13%;
  }
  .xf-table--mds thead th,
  .xf-table--mds tbody td {
    padding: 0 0.3rem;
  }
  .xf-table--mds .custom-datatable__sort-header {
    padding: 0 0.3rem;
  }
}


/* =============================================================
   Homepage table - MDS retheme, card mode (≤1035px)
   .xf-table--mds (icori.css) only ever styled the desktop layout
   (fixed column widths via --col-* vars, a column-aligned detail
   grid). This block gives it the same "row -> card" treatment
   .custom-datatable--card-mobile already has for results-list.html,
   adapted for its one structural difference: the checkbox and row
   number share a single <td> here instead of two separate cells.

   Cuts over at 1035px, not the 767px mobile breakpoint everything else
   here uses - even with both squeeze tiers above, the table has no
   more room to give below that without genuinely clipping the Download
   button (see the squeeze tiers' own notes). Below 1036px, cards are
   the only way to keep it readable without clipping.

   Two cards per row down to 851px, one per row below that (the Result
   badges start wrapping onto a second line inside a half-width card
   around there) - see the grid rule and its ≤851px override further
   down this block. */
@media (max-width: 1035px) {
  /* xfact-custom-responsive.css has a generic .xf-table-wrapper rule at its
     own, narrower ≤768px breakpoint that bleeds ANY .xf-table-wrapper
     edge-to-edge (negative margin canceling the .xf-layout page gutter +
     width beyond 100%) for the horizontally-scrolling table variant. This
     wrapper also carries the plain .xf-table-wrapper class, so below 768px
     it inherited that bleed even though card mode doesn't scroll - cancel
     it back to the page's normal padded width. Applied across this whole
     block's wider ≤1035px range regardless (not just ≤768px): the outer
     wrapper border/radius need to go the same way up to 1035px too, since
     each row is its own bordered card there (see .results-row below) - an
     outer box around a stack of already-boxed cards would double up. */
  .xf-table-wrapper.xf-table--mds {
    border: none;
    border-radius: 0;
    margin-left: 0;
    margin-right: 0;
    width: 100%;
  }

  /* xfact-custom-responsive.css also forces the plain .xf-table variant's
     <table> itself to min-width: 540px at <=480px (its "force horizontal
     scroll" trick). This table carries the plain .xf-table class too, so it
     inherited that forced width even in card mode, where tbody/tr are
     flexed to 100% of the table's own box - result: each card renders up to
     540px wide inside a viewport that's often narrower, pushing the right
     edge off-screen. Card mode doesn't scroll, so cancel it back down to
     the wrapper's actual width. */
  .xf-table--mds {
    min-width: 0;
    width: 100%;
  }

  /* Hide the header - labels come from data-label instead. A plain
     display:none (not the position:absolute/clip "visually hidden"
     trick - that doesn't reliably collapse a real thead/tr/th; this is
     the same technique .custom-datatable--card-mobile already uses for
     results-list.html, see mds-responsive.css). */
  .xf-table--mds thead {
    display: none;
  }

  /* Two cards per row from 1035px down to 851px (see the ≤851px override
     below this block for the one-per-row tier beneath that) - each visible
     .results-row is a grid item; its sibling .results-detail row stays
     display:none (see further down) so it never consumes a track of its
     own. align-items: start, not the grid default of stretch - an expanded
     card (taller, showing its relocated detail content) would otherwise
     stretch its shorter row-mate to match, leaving visible dead space
     inside the shorter card. Column-gap only (row-gap: 0): vertical
     spacing between cards already comes from each .results-row's own
     margin-bottom below, so a row-gap on top of that would double it up.
     space-6 (24px), not space-4 - the wider gap reads better between two
     cards; it also eats a bit more of each card's own width, which is why
     the one-per-row cutover below moved up from 843px to 851px to match. */
  .xf-table--mds tbody {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 0 var(--space-6);
  }
  /* Empty-state row spans both columns - same exclusion as custom-datatable
     above: JS moves td.results-detail-cell[colspan] into .results-row.
     Card border added here (not just at ≤767px from the generic .xf-table rule)
     so the box is consistent across the full 1035px card-mode range. */
  .xf-table--mds tbody tr:not(.results-row):not(.results-detail):has(> td[colspan]) {
    grid-column: 1 / -1;
    border: 1px solid #dcdcdc;
    border-radius: 8px;
    background-color: #ffffff;
    overflow: hidden;
  }

  /* Each record (results-row + its results-detail) -> one bordered card. */
  .xf-table--mds tbody tr.results-row {
    display: flex;
    flex-wrap: wrap;
    height: auto;
    margin-bottom: var(--space-6);
    padding: 0 var(--space-4);
    background-color: #ffffff;
    border: 1px solid #dcdcdc;
    border-radius: 8px;
    overflow: hidden;
  }
  /* No zebra in card mode - flatten the desktop record striping to white. */
  .xf-table--mds tbody tr:nth-child(4n+1),
  .xf-table--mds tbody tr:nth-child(4n+2),
  .xf-table--mds tbody tr:nth-child(4n+3),
  .xf-table--mds tbody tr:nth-child(4n) {
    background-color: #ffffff;
  }
  /* icori.css strips border-bottom off the last record's results-row
     (it's followed by the last, desktop-only, :last-child detail row) so
     the desktop table doesn't double up its own bottom border. In card
     mode each record is a fully-bordered box, so the last card still needs
     its own bottom edge - restore it. Same selector/specificity as that
     rule, so this wins purely on source order (this file loads after
     icori.css). */
  .xf-table--mds tbody tr.results-row:has(+ tr.results-detail:last-child),
  .xf-table--mds tbody tr.results-row.xf-pg-last-row {
    border-bottom: 1px solid #dcdcdc !important;
  }

  /* Each cell -> its own "label : value" row. Overrides the generic
     .xf-table card-mode rules (xfact-custom-style.css), which also match
     this table (it carries both .xf-table and .xf-table--mds) and fight
     for order/background/border on :first-child, :last-child, and the
     sibling-selected border-top between middle cells - !important here
     is deliberate, not stylistic, to guarantee this table's own card
     layout wins outright rather than depending on selector-specificity
     arms-races against that base rule. */
  .xf-table--mds tbody td {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: var(--space-2) !important;
    height: auto !important;
    width: 100% !important;
    flex: 0 0 100% !important;
    padding: var(--space-3) 0 !important;
    text-align: right !important;
    background-color: transparent !important;
    font-size: var(--type-size-base) !important;
    font-weight: normal !important;
    border-top: none !important;
    border-bottom: 1px solid var(--color-gray-200) !important;
    /* Long unbreakable values wrap inside the card, not past its edge. */
    overflow-wrap: anywhere;
  }
  /* The desktop table's nowrap is inherited by the card and defeats the overflow-wrap above,
     so long subject and client names ran past the card edge (17853). Text-valued fields only. */
  .xf-table--mds tbody td[data-label="Subject"],
  .xf-table--mds tbody td[data-label="Client organization"] {
    white-space: normal !important;
  }
  .xf-table--mds tbody td::before {
    /* xfact-custom-style.css's generic .xf-table tbody td[data-label]::before
       rule (for the 7 plain .xf-table pages) has an attribute-selector bump
       that outranks this un-attributed selector on specificity alone - same
       class of bug as the earlier order/background fights above. !important
       needed to guarantee the label renders without a trailing colon. */
    content: attr(data-label) !important;
    flex: 0 0 auto;
    font-weight: var(--font-weight-semibold, 600);
    text-align: left;
  }
  .xf-table--mds tbody td[colspan] {
    display: block !important;
    text-align: center !important;
    justify-content: center !important;
    font-size: var(--type-size-base) !important;
    font-weight: normal !important;
    padding: 1.5rem 0 !important;
    border-bottom: none !important;
  }
  .xf-table--mds tbody td[colspan]::before {
    content: none !important;
  }

  /* Explicit visual order for every column (the generic .xf-table rule
     above also assigns order: 1 to BOTH :first-child and :last-child, and
     order: 2 to every middle cell - that's what was pushing Actions to
     the very top, tied with the checkbox+No. cell). Keyed off data-label /
     class rather than nth-child so a future desktop column reorder can't
     silently break this without a matching edit here. Details comes before
     Result (order 5 then 6, matching the desktop column order - see
     homepage.html and icori.css's --col-* widths), so a card reads
     "[Show Details]  [Result badge]"; the relocated detail content (order
     7, see further down) renders full-width below that line, not between
     them, when expanded. */
  .xf-table--mds tbody td[data-label="No."]       { order: 1 !important; }
  .xf-table--mds tbody td[data-label="Date/time"] { order: 2 !important; }
  .xf-table--mds tbody td[data-label="Subject"]   { order: 3 !important; }
  .xf-table--mds tbody td[data-label="Client organization"] { order: 3 !important; }  /* CRA only (17853); same order as Subject, so DOM order puts it right after */
  .xf-table--mds tbody td[data-label="Status"]    { order: 4 !important; }
  .xf-table--mds tbody td.results-row__toggle     { order: 5 !important; }  /* Details */
  .xf-table--mds tbody td[data-label="Result"]    { order: 6 !important; }
  .xf-table--mds tbody td[data-label="Actions"]   { order: 8 !important; }  /* Actions, always last */

  /* First cell (checkbox + No.) is the card's header band, not a plain
     labelled field: light blue-tint background bled to the card's full
     edges (the row itself carries the horizontal inset, so cancel it here
     with a matching negative margin). No colon on this one (it isn't a
     label/value pair) - plain "No." - and the checkbox comes first, on
     the left: "[ ] No. 1". DOM order is checkbox then number, so only the
     label needs reordering ahead of both. */
  .xf-table--mds tbody td[data-label="No."] {
    flex-direction: row !important;
    justify-content: flex-start !important;
    /* flex-basis (set via the shorthand below), not width, governs a flex
       item's main-axis size once it's non-auto - the generic td rule above
       sets flex: 0 0 100%, so a plain width override here would be ignored. */
    flex: 0 0 calc(100% + (var(--space-4) * 2)) !important;
    margin: 0 calc(var(--space-4) * -1) !important;
    padding: var(--space-3) var(--space-4) !important;
    background-color: var(--color-berkshires-green-100) !important;
    border-bottom: 1px solid #dcdcdc !important;
  }
  .xf-table--mds tbody td[data-label="No."]::before {
    content: attr(data-label) !important;
    order: 1;
  }
  .xf-table--mds tbody td[data-label="No."] .xf-table-check { order: 0; }
  .xf-table--mds tbody td[data-label="No."] span { order: 2; }

  /* Details + Result share one line: "[Show Details]  [Result badge]".
     Each cell's own box takes exactly half the row - no flex column-gap
     between them (a gap leaves a strip that belongs to neither box, which
     is exactly what was breaking each cell's border-bottom into two
     separate segments with a blank gap in the middle instead of one
     continuous line). The visual breathing room between the button and
     the badge instead comes from ordinary padding-right on the toggle
     cell (see below) - real box, real border, just internal spacing.

     Each cell also gets its own explicit min-width floor instead of the
     generic min-width:0 override the row's other cells inherit. The
     toggle's floor (10rem/160px) covers its own worst case - icon +
     "Show Details" / "Hide Details", unable to wrap onto a second line
     inside the button - with some headroom; the Result floor (6rem/96px)
     is lower because its badge text CAN wrap onto a second line (see
     .icori-result-badge, deliberately not white-space:nowrap), so it
     needs less room before that's a better outcome than crowding. Below
     the combined floor, flex-wrap on the row (see above) drops the second
     cell to its own full-width line - e.g. sub-360px viewports - rather
     than squeezing either one unreadably thin; above it, both sit at a
     clean 50/50 split. */
  .xf-table--mds tbody td.results-row__toggle,
  .xf-table--mds tbody td[data-label="Result"] {
    flex: 1 1 50% !important;
  }
  .xf-table--mds tbody td.results-row__toggle {
    min-width: 10rem !important;
    justify-content: flex-start !important;
    /* The space between the toggle button and the badge - internal
       padding, not a flex gap, so the border-bottom below still runs
       edge-to-edge across both cells with no visible break. */
    padding-right: var(--space-3) !important;
  }
  .xf-table--mds tbody td.results-row__toggle::before { content: none !important; }
  /* The toggle stays at its normal desktop (.mds-btn--sm) size on mobile -
     only the Actions button (below) gets bumped up to MD size here. Its
     width IS stretched to fill the toggle cell's full half, though - see
     .results-expander below - so it visually shares the line evenly with
     the Result badge (also stretched to its own half, see further down)
     instead of shrinking to its own label width and leaving blank space
     inside its half of the row. */
  .xf-table--mds .results-expander {
    width: 100%;
  }

  /* This table's own card mode now runs all the way up to 1035px (see this
     block's own @media above), but the shared .results-expander__noun rule
     further down this file still hides the noun starting at the generic
     768px mobile breakpoint - written for results-list.html's card mode,
     which still cuts over there. Between 768px and 1035px this table is in
     card mode while that generic rule would otherwise hide the noun, so
     restore it here, scoped to this table only; results-list.html is
     untouched since it never carries .xf-table--mds. */
  .xf-table--mds .results-expander__noun {
    display: inline;
  }

  .xf-table--mds tbody td[data-label="Result"] {
    min-width: 6rem !important;
  }
  /* Result keeps its "Result:" label only when it has no badge to show
     instead (the empty/pending "..." placeholder) - mirrors the Actions
     cell's own populated-vs-empty label rule further down, so an empty
     Result row reads "Result: ..." next to "Show Details" the same way an
     empty Actions row reads "Actions: ...". Once a badge is present, the
     label is redundant (the badge already says what it is) and is dropped. */
  .xf-table--mds tbody td[data-label="Result"]:has(.icori-result-badge)::before {
    content: none !important;
  }
  /* Populated: the badge itself stretches to fill the cell's full half
     (mirrors .results-expander above) - its own centered text (see
     .icori-result-badge) then reads centered within that full-width pill,
     matching the toggle button's width exactly. */
  .xf-table--mds tbody td[data-label="Result"] .icori-result-badge {
    width: 100%;
  }
  /* Empty: no badge to stretch, so instead group the "Result:" label and
     the "..." placeholder together and push that pair to the right edge
     of the cell (overriding the generic space-between, which would spread
     a short label and a short value across the whole half-width cell). */
  .xf-table--mds tbody td[data-label="Result"]:not(:has(.icori-result-badge)) {
    justify-content: flex-end !important;
  }

  /* Result / Actions labels are secondary to their visual content (badge, button). */
  .xf-table--mds tbody td[data-label="Result"]::before,
  .xf-table--mds tbody td[data-label="Actions"]::before {
    font-weight: normal !important;
  }

  /* Actions is the card's last row, a full-width CTA button when it holds
     one; an empty state ("...") stays a normal label/value row. Either
     way it's the final row, so no bottom divider under it. */
  .xf-table--mds tbody td[data-label="Actions"] {
    border-bottom: none !important;
  }
  /* No button (pending "..."): pull label + value to the left so "Actions  ..."
     reads as a pair rather than spreading across the full card width. */
  .xf-table--mds tbody td[data-label="Actions"]:not(:has(.mds-btn)) {
    justify-content: flex-start !important;
    gap: var(--space-2) !important;
  }
  .xf-table--mds tbody td[data-label="Actions"]:has(.mds-btn) {
    padding-top: var(--space-3) !important;
  }
  .xf-table--mds tbody td[data-label="Actions"]:has(.mds-btn)::before { content: none !important; }
  /* Download is the one primary action on the card - bumped to MD size
     (16px / more padding) so it stands out and is easy to tap, unlike the
     Show/Hide toggle above which stays at its normal small size. */
  .xf-table--mds tbody td[data-label="Actions"] .mds-btn {
    width: 100%;
    font-size: var(--type-size-base) !important;   /* 16px, MD size */
    padding: var(--space-3) var(--space-4) !important;
  }

  /* tr.results-detail is emptied out by JS (its .results-detail-cell moves
     into results-row, see homepage.html's script) as soon as the page loads
     at a mobile width, so the row itself never needs to show. */
  .xf-table--mds tbody tr.results-detail { display: none !important; }

  /* The relocated detail content: just another cell in the card's own flex
     flow, ordered right after the Result+Details line (order 5 and 6) so
     it renders full-width below that merged line - not squeezed between
     them - when expanded. No separate "merge two cards into one" seam
     trick needed anymore; it's already part of the one bordered card. */
  .xf-table--mds tbody tr.results-row > td.results-detail-cell {
    /* The generic .xf-table--mds tbody td rule above sets display:flex
       !important - a plain display:none here would lose to it (important
       beats non-important regardless of specificity), leaving this cell
       visible at all times no matter the row's expanded state. Needs
       !important too. */
    display: none !important;
    order: 7;
    width: 100% !important;
    flex: 0 0 100% !important;
    padding: var(--space-3) 0 !important;
    border-bottom: 1px solid var(--color-gray-200) !important;
  }
  .xf-table--mds tbody tr.results-row > td.results-detail-cell::before {
    content: none !important;
  }
  .xf-table--mds tbody tr.results-row.is-expanded > td.results-detail-cell {
    display: block !important;
  }
  /* icori.css strips border-bottom from .xf-table--mds .results-row.is-expanded to
     seamlessly join it with its desktop detail row. That rule has no @media guard, so
     it also fires in card mode and removes the card's outer bottom edge. Restore it. */
  .xf-table--mds tbody tr.results-row.is-expanded {
    border-bottom: 1px solid #dcdcdc !important;
  }

  /* Drop the desktop column-alignment divider (positioned via --col-num,
     meaningless once the columns collapse into a card) and the blank
     placeholder div that stood in for the checkbox+No. column. */
  .xf-table--mds .results-detail__grid > [aria-hidden="true"]:first-child {
    display: none;
  }
  .xf-table--mds .results-detail__grid {
    grid-template-columns: 1fr;
    gap: 0;
    padding-top: 0;
    padding-bottom: 0;
  }
  .xf-table--mds .results-detail__item {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-1) 0;
  }
  /* Keep the field label on one line (matches the .custom-datatable--card-mobile
     tables, which already set this). Without it the label and value share flex
     shrink equally, so a long value (an email login ID) squeezes the wider
     "Requestor Login ID" label into wrapping too - but only in the narrow band
     of widths where shorter-labelled fields still fit on one line, so that one
     field wraps inconsistently with the rest. flex-shrink: 0 pins the label to
     its content width and lets only the value wrap when space is tight. */
  .xf-table--mds .results-detail__label { flex-shrink: 0; }
  .xf-table--mds .results-detail__value { text-align: right; }
}

/* One card per row below 851px - measured empirically: that's where the
   Result badges (CRIMINAL HISTORY / NO AVAILABLE CORI) start wrapping onto
   a second line inside a half-width card, which reads as cramped. Not tied
   to the Filter and sort panel's own 767px default-open/closed cutover -
   the two just happen to be close; this one is set by the badges alone. */
@media (max-width: 851px) {
  .xf-table--mds tbody {
    grid-template-columns: 1fr;
  }
}

/* Above the mobile card breakpoint, the "Details" column header already
/* =============================================================
   Uniform card-mode visual - all custom-datatable--card-mobile tables
   Brings every table in the app in line with the homepage's
   xf-table--mds card appearance so mobile cards look identical
   across results, account, consent, and any future pages.
   Source-order wins over the vendor mds-responsive.css rules at
   equal specificity; no !important needed.
   ============================================================= */
@media (max-width: 767px) {
  .custom-datatable--card-mobile tbody tr {
    border-radius: var(--radius-md);
    margin-bottom: var(--space-6);
    padding: 0 var(--space-4);
    border: 1px solid #dcdcdc;
    background-color: #ffffff;
    overflow: hidden;
  }
  .custom-datatable--card-mobile tbody td {
    font-size: var(--type-size-base);
    font-weight: normal;
    align-items: center;
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--color-gray-200);
    /* Long unbreakable values wrap inside the card, not past its edge. */
    overflow-wrap: anywhere;
  }
  /* Tinted header band on the No. row - bleeds edge-to-edge inside the card,
     matching the results table card treatment. */
  .custom-datatable--card-mobile tbody td[data-label="No."] {
    margin: 0 calc(var(--space-4) * -1);
    padding: var(--space-3) var(--space-4);
    background-color: var(--color-berkshires-green-100);
    border-bottom: 1px solid var(--color-gray-200);
    justify-content: flex-start;
    gap: var(--space-2);
  }

  .custom-datatable--card-mobile tbody td:last-child,
  .custom-datatable--card-mobile tbody td[colspan] {
    border-bottom: none;
  }
  .custom-datatable--card-mobile tbody td[colspan] {
    display: block !important;
    text-align: center !important;
    justify-content: center !important;
    font-size: var(--type-size-base);
    font-weight: normal;
    padding: 1.5rem 0;
  }
  .custom-datatable--card-mobile tbody td[colspan]::before {
    content: none !important;
  }
  .custom-datatable--card-mobile tbody td::before {
    content: attr(data-label);
    font-size: var(--type-size-base);
    font-weight: var(--font-weight-semibold, 600);
    color: inherit;
    text-transform: none;
    letter-spacing: normal;
    margin-right: var(--space-2);
  }
}


/* =============================================================
   Org header bar (.xf-org-header): name + badge + cancel button
   Desktop: single row — name grows, button pinned far right.
   ≤900px: name wraps to its own row; badge and cancel split 50/50
   on the row below with matching heights.
   ============================================================= */
.xf-org-header .mds-btn { margin-left: auto; }

@media (max-width: 900px) {
  .xf-org-header .org-name-label {
    flex: 0 0 100%;
  }
  .xf-org-header .mds-badge {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 37px;
    border-radius: var(--radius-md);
  }
  .xf-org-header .mds-btn {
    flex: 1 1 0;
    margin-left: 0;
    justify-content: center;
  }
}


/* =============================================================
   Request / account form grids
   Request forms (single / edit / batch) use a 4-col base; account
   edit forms (individual / organization) use a 3-col base. Both
   collapse to 2 cols on tablet and 1 col on mobile. Templates
   position cells with inline grid-column spans, so each breakpoint
   reflows every cell and re-asserts which ones stay full-width
   (.icori-grid-full, legends, and .icori-section-description - the last
   carries grid-column:1/-1 by class, so it must be re-exempted or the
   !important span-1 reset narrows it). Empty spacer <div>s are hidden.
   The org account
   form groups fields in `<fieldset style="display:contents">`, so those
   fields are grid GRANDCHILDREN; the `> fieldset > *` selectors below
   reflow them (legends stay full-width, empty spacers hidden) exactly
   like direct children - otherwise the 3-col spacers survive into the
   2-col tier and ragged-pair the fields (a field alone left or right).
   ============================================================= */

/* Tablet: 2 columns */
@media (max-width: 1024px) {
  .icori-request-grid,
  .icori-account-grid,
  .icori-account-grid--4col { grid-template-columns: repeat(2, 1fr); }
  .icori-request-grid > *,
  .icori-account-grid > *,
  .icori-account-grid--4col > *,
  .icori-account-grid > fieldset > * { grid-column: auto / span 1 !important; }
  .icori-request-grid > .icori-grid-full,
  .icori-account-grid > .icori-grid-full,
  .icori-account-grid--4col > .icori-grid-full,
  .icori-account-grid > .icori-section-description,
  .icori-account-grid > fieldset > .icori-grid-full,
  .icori-account-grid > fieldset > .icori-section-description,
  .icori-account-grid > fieldset > legend { grid-column: 1 / -1 !important; }
  .icori-request-grid > div:empty,
  .icori-account-grid > div:empty,
  .icori-account-grid--4col > div:empty,
  .icori-account-grid > fieldset > div:empty { display: none; }
}

/* Mobile: single column */
@media (max-width: 767px) {
  .icori-request-grid,
  .icori-account-grid,
  .icori-account-grid--2col,
  .icori-account-grid--4col { grid-template-columns: 1fr !important; }
  .icori-request-grid > *,
  .icori-request-grid > .icori-grid-full,
  .icori-account-grid > *,
  .icori-account-grid > .icori-grid-full,
  .icori-account-grid > fieldset > * { grid-column: 1 / -1 !important; }
  .icori-request-grid > div:empty,
  .icori-account-grid > div:empty,
  .icori-account-grid > fieldset > div:empty { display: none; }

  /* Nested address / two-up sub-grids inside the indigency affidavit */
  .icori-address-grid { grid-template-columns: 1fr !important; }
  .icori-address-grid > * {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
  }
  .icori-subgrid-2 { grid-template-columns: 1fr !important; }

  /* Action buttons stack full-width instead of a cramped row */
  .icori-request-actions {
    flex-direction: column;
    align-items: stretch !important;
  }
  .icori-request-actions > * {
    margin-left: 0 !important;
    width: 100%;
    text-align: center;
  }
}


/* =============================================================
   Form fields with a desktop max-width cap (consent "Find account",
   the account add/invite forms, etc). Inputs carry an inline max-width
   cap (e.g. 24rem) so a single-column form reads at a comfortable width
   on desktop/tablet instead of stretching. On mobile, drop the cap so
   they fill the column full-width.
   ============================================================= */
@media (max-width: 767px) {
  .icori-consent-field,
  .icori-form-field { max-width: none !important; }
}



/* Desktop: hide "Details" noun on expander button - reads just "Show"/"Hide" */
@media (min-width: 1036px) {
  .results-expander__noun {
    display: none;
  }
}

/* Mobile: toolbar sticky + icon-only buttons.
   Pins directly under the nav bar once scrolled past it (position:sticky +
   --icori-nav-h published by the nav controller in base.html). Desktop leaves
   the bar in normal flow - enough real estate that pinning isn't needed. */
@media (max-width: 767px) {
  .results-table-toolbar {
    align-items: center;
    margin-bottom: var(--space-1);
    position: sticky;
    top: var(--icori-nav-h, 0px);
    z-index: var(--z-sticky);             /* 1020 - below .mds-filters (1030) so filter dropdowns show above it */
    background-color: var(--color-white);
    padding: var(--space-2) 0;
    transition: box-shadow var(--transition-fast);
  }
  /* Once the toolbar pins to the top it must clear the filter's stacking
     context (1030) so it isn't painted over. JS adds --stuck when pinned. */
  .results-table-toolbar--stuck {
    z-index: calc(var(--z-sticky) + 10);  /* 1032 */
  }

  /* Full-bleed white background via box-shadow spread + clip-path (no 100vw
     tricks that cause horizontal scroll). Sits behind the toolbar content at z:-1. */
  .results-table-toolbar::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    box-shadow: 0 0 0 100vmax var(--color-white);
    clip-path: inset(0 -100vmax);
  }

  /* Stuck-state drop shadow - a full-bleed gradient bar via left/right geometry
     (box-shadow spread can't produce a gradient). opacity toggled by JS. */
  .results-table-toolbar::after {
    content: "";
    position: absolute;
    left: -100vmax;
    right: -100vmax;
    bottom: -8px;
    height: 8px;
    z-index: -1;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0));
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast);
  }
  .results-table-toolbar--stuck::after {
    opacity: 1;
  }

  /* The ::after bleeds via left/right:-100vmax which DOES contribute to scrollable
     overflow (unlike box-shadow). Contain it at body without creating a scroll
     container (overflow-x:hidden would, clip doesn't). */
  body {
    overflow-x: clip;
  }
  .results-table-toolbar--stuck .icori-action-link {
    font-size: var(--type-size-sm);
  }
  .results-table-toolbar--stuck .icori-action-link svg {
    width: 16px;
    height: 16px;
  }

  /* When toolbar is stuck under the nav, hand shadow duty to the toolbar so
     there's no seam between the two pinned headers. */
  body:has(.results-table-toolbar--stuck) .mds-nav--stuck {
    box-shadow: none;
  }

  .results-table-toolbar__select { padding-left: 0; }
  .results-table-toolbar__actions {
    justify-content: flex-end;
    gap: var(--space-3);
    padding-right: 0;
  }
  .results-table-toolbar__actions .xf-toolbar-divider { display: none; }

  /* Icon-only square buttons - hide text labels, show 40×40 outlined icon.
     Matches the home-layout homepage pattern. */
  .results-table-toolbar__actions .icori-action-link {
    width: 40px;
    height: 40px;
    padding: 8px;
    gap: 0;
    box-sizing: border-box;
    justify-content: center;
    border: 2px solid var(--color-berkshires-green);
    border-radius: var(--radius-md);
    color: var(--color-berkshires-green);
  }
  .results-table-toolbar__actions .icori-action-link:hover {
    background-color: var(--color-berkshires-green);
    color: var(--color-text-inverse);
  }
  .results-table-toolbar__actions .icori-action-link:active {
    background-color: var(--color-primary-active);
    border-color: var(--color-primary-active);
    color: var(--color-text-inverse);
  }
  .results-table-toolbar__actions .icori-action-link--disabled {
    border-color: var(--color-gray-300);
    color: var(--color-text-disabled);
  }
  .results-table-toolbar__actions .icori-action-link svg {
    width: 22px;
    height: 22px;
  }
  .results-table-toolbar__actions .xf-toolbar-label,
  .results-table-toolbar__actions .xf-toggle-all-label-stack {
    display: none;
  }

}
