/* Responsive card mode for every table the CRM shell renders (2026-08-17,
   made universal 2026-09-13 under d-2026-09-13-040).
   Desktop keeps the table; under 768px each row becomes a labelled card.
   Labels come from data-label attributes stamped by erpal-resptable.js and, for
   anything rendered through a render array, by the theme's own preprocess. */

/* ── THE SCROLL FRAME ───────────────────────────────────────────────────────
   The other half of card mode, and the reason "opt out" is safe. A table that
   must stay a table on a phone (an email body's layout tables, a knowledge
   record's third-party report, a calendar grid) keeps its natural column widths
   and SCROLLS; it is never allowed to crush instead. The mobile gate encodes
   the same contract from the other side — it exempts cells inside this class
   from its 120px minimum and fails every narrow cell outside one. */
.erpal-scrollframe {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}
.erpal-scrollframe > table {
  /* Inside a scroll frame the table sizes to its CONTENT, which is the whole
     point — `table-layout: fixed` from the shell's shrink rules would defeat
     the frame by squeezing the table back into the viewport.
     `width: auto` was not enough and measuring proved it: a table inside a
     narrow block still shrink-to-fits its container, so fleet_watch's payload
     dump sat at 145px inside the frame and wrapped exactly as before. Ask for
     max-content and floor it at the frame's width. */
  table-layout: auto !important;
  width: max-content;
  max-width: none;
  min-width: 100%;
}
/* Machine output inside a frame is read by SCROLLING, not by wrapping: a
   collector payload is one 358-character JSON token and there is no line break
   that helps. */
.erpal-scrollframe > table.fw-kv td { white-space: pre; }
.erpal-scrollframe:focus-visible {
  outline: 2px solid var(--erpal-accent, #2563eb);
  outline-offset: 2px;
}

/* The sort strip only exists where the header does not — see sortBar() for why
   it exists at all. Above the breakpoint the real header is right there. */
.erpal-sortbar { display: none; }

@media (max-width: 767px) {
  table.erpal-resptable thead { display: none; }

  .erpal-sortbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    margin: 0 0 .55rem;
    font-size: .78rem;
  }
  .erpal-sortbar__lead {
    color: var(--erpal-muted, #6b7280);
    text-transform: uppercase;
    letter-spacing: .03em;
    font-weight: 600;
  }
  .erpal-sortbar__link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;          /* a thumb target, like every other control here */
    padding: 0 .6rem;
    border: 1px solid var(--erpal-border, #e5e7eb);
    border-radius: 999px;
    background: var(--erpal-surface, #fff);
    /* A CHIP IS A BUTTON, AND IT HAS TO PASS AA LIKE ONE. These are real <a>
       elements cloned out of the header, so the shell's link colour applied and
       the contrast gate measured 3.09:1 on /deals at 390 — a miss this file
       introduced, caught on the promote it shipped in. `:link` and `:visited`
       are named explicitly because the bare class loses to `a:link` on
       specificity ties and the chip would silently go blue again. */
    color: var(--erpal-text, #111827);
    text-decoration: none;
    white-space: nowrap;
  }
  .erpal-sortbar__link:link,
  .erpal-sortbar__link:visited,
  .erpal-sortbar__link:hover,
  .erpal-sortbar__link:focus { color: var(--erpal-text, #111827); }
  .erpal-sortbar__link.is-active {
    border-color: var(--erpal-accent, #2563eb);
    font-weight: 600;
  }
  /* A HEADER ROW IS NOT ALWAYS IN A <thead>. Hand-written tables put the <th>
     row straight in the implicit tbody; erpal-resptable.js marks it. */
  table.erpal-resptable tr.erpal-headrow { display: none; }
  table.erpal-resptable, table.erpal-resptable tbody { display: block; width: 100%; }

  /* CARD MODE OUTRANKS THE SHELL'S SHRINK RULES. app.css narrows every table on
     a phone with `table-layout: fixed` + `overflow-wrap: anywhere`, which is a
     reasonable last resort for a table that stays a table and is catastrophic
     for one that does not: measured on the owner's screenshot, six columns of a
     390px screen is 53px each, and `anywhere` then breaks a decision id into
     one character per line. A card has no columns to shrink, so both rules are
     switched off here rather than left to specificity. */
  table.erpal-resptable {
    table-layout: auto;
    border-collapse: collapse;
  }

  table.erpal-resptable tbody tr,
  table.erpal-resptable > tr {
    display: block;
    margin: 0 0 .65rem;
    padding: .55rem .8rem;
    border: 1px solid var(--erpal-border, #e5e7eb);
    border-radius: 10px;
    background: var(--erpal-surface, #fff);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
  }

  /* THE CARD OWNS THE SIDE PADDING, NOT THE CELL (2026-09-28, d-2026-09-27-019).
     app.css pads every listing cell `8px 14px` through `.erpal-content table
     tbody td` (0,1,3), which outranks this file's `padding: .18rem 0` on
     `table.erpal-resptable td` (0,1,2) — so in card mode every value sat inside
     the card's own .8rem AND a second 14px each side. Measured on the multisite
     demo's /invoices at 390: the value column was 292px of a 348px card, and an
     invoice subject like "INV-2026-0311 — Foothill Co-op onboarding" wrapped to
     two lines, putting the page's prose median at 3 words a line (mobile gate
     floor 4). Giving the 28px back makes the same subject one line and the page
     median 4. Horizontal only: the row rhythm (8px top/bottom, the divider) is
     unchanged, and a continuation cell keeps its own indent. */
  .erpal-content table.erpal-resptable tbody td:not(.erpal-td-cont) {
    padding-left: 0;
    padding-right: 0;
  }

  table.erpal-resptable td {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    padding: .18rem 0;
    border: 0;
    font-size: .85rem;
    /* `break-word`, NOT `anywhere`: a card gives a value the room it needs, so
       a word should only ever break when it genuinely cannot fit. `anywhere`
       is what turns "Example Co of Technology" into "Orego/n Institut/e"
       and a decision id into a vertical column of characters. */
    overflow-wrap: break-word;
    word-break: normal;
    min-width: 0;
    width: auto;
  }

  table.erpal-resptable td::before {
    content: attr(data-label) ": ";
    flex: 0 0 34%;
    max-width: 34%;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--erpal-muted, #6b7280);
  }

  /* A LONG VALUE GETS THE WHOLE CARD, LABEL ABOVE IT.
     With the label beside it, a value column is 66% of a 390px card minus
     padding — 159px measured — and the mobile gate calls anything over 25
     characters at that width crushed prose, correctly: /leads failed on a
     single 27-character email address rendered exactly there, on a page that
     had had card mode for four weeks. The stamper marks any cell over the
     gate's own prose threshold, so "long enough to need room" means the same
     thing in the layout and in the gate that checks it. */
  table.erpal-resptable td.erpal-td-long { display: block; }
  table.erpal-resptable td.erpal-td-long::before {
    display: block;
    flex: none;
    max-width: none;
    margin-bottom: .1rem;
  }

  /* Empty cells add nothing on a card. */
  table.erpal-resptable td:empty { display: none; }

  /* NO LABEL, NO COLON — FAIL-SAFE, NOT BEST-EFFORT.
     `content: attr(data-label) ": "` prints ": " for any cell the stamper never
     labelled, and there are three ways to be that cell: a column whose <th> is
     blank (the truck board's origin state, which leaves its header empty so the
     DESKTOP table reads the lane across two columns), the checkbox column that
     precedes every header, and a cell some OTHER behaviour appends to the row
     after this one has run — erpal_tidy's row-action cell does exactly that, and
     it is why the LD hub's own /leads cards have carried a bare ": " above the
     edit icons. Draw the label from the ATTRIBUTE'S PRESENCE rather than from
     its value, so a cell nobody labelled is silently unlabelled however it got
     there, and no JS ordering has to be right for the card to read correctly. */
  table.erpal-resptable td:not([data-label])::before,
  table.erpal-resptable td.erpal-td-cont::before { content: none; }
  /* A continuation aligns under the VALUE it continues, not under the labels. */
  table.erpal-resptable td.erpal-td-cont {
    padding-top: 0;
    padding-inline-start: calc(34% + .6rem);
  }
  table.erpal-resptable td.erpal-td-cont.erpal-td-long { padding-inline-start: 0; }

  /* Bulk-select checkbox column: no label, inline compact. */
  table.erpal-resptable td.views-field-operations::before,
  table.erpal-resptable td:has(> input[type="checkbox"]:only-child)::before { content: none; }
  table.erpal-resptable td:has(> input[type="checkbox"]:only-child) { padding: 0 0 .25rem; }

  /* A CELL THAT IS A CONTROL IS A CONTROL, NOT A FIELD.
     The desk's per-row "Mark executed" lives in a header-less last column. In a
     53px table cell it rendered as a vertical stack of fourteen letters — 44px
     tall and 20px wide, which is exactly why a tap-target check measuring HEIGHT
     passed it. On a card the button is the row's action: full width, one line,
     and a thumb-sized target. */
  table.erpal-resptable td.erpal-td-action { display: block; padding-top: .4rem; }
  table.erpal-resptable td.erpal-td-action::before { content: none; }
  table.erpal-resptable td.erpal-td-action > button,
  table.erpal-resptable td.erpal-td-action > input[type="submit"],
  table.erpal-resptable td > button,
  table.erpal-resptable td > input[type="submit"] {
    display: block;
    width: 100%;
    min-height: 44px;
    white-space: nowrap;
  }

  /* Phone cells: keep call + text side by side, numbers unbroken. */
  table.erpal-resptable .erpal-celllink { white-space: nowrap; }

  /* A KEY/VALUE TABLE HAS NO HEADER TO LABEL WITH — it IS label and value.
     fleet_watch's .fw-kv is the fleet's example: two columns, the left one a
     field name. Measured at 390 before this rule: the key column rendered at
     106px and "localliving-press-release-poller.service,mail-…" wrapped one
     word per line in the other. Stack the pair instead. */
  table.erpal-resptable-kv,
  table.erpal-resptable-kv tbody { display: block; width: 100%; }
  table.erpal-resptable-kv tbody tr,
  table.erpal-resptable-kv > tr {
    display: block;
    padding: .35rem 0;
    border-bottom: 1px solid var(--erpal-border, #e5e7eb);
  }
  table.erpal-resptable-kv td {
    display: block;
    border: 0;
    padding: 0;
    width: auto;
    overflow-wrap: break-word;
    word-break: normal;
  }
  table.erpal-resptable-kv td:first-child {
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--erpal-muted, #6b7280);
  }
}

@media (max-width: 767px) {
  table.erpal-resptable td.erpal-td-empty { display: none; }
}


/* ── WHERE ANOTHER CARD DESIGN ALREADY WON ─────────────────────────────────
   The CRM listing tables (/leads and its siblings) have had erpal_tidy's own
   phone card since before this file existed: `.erpal-app .erpal-listing table
   tbody tr` is a flex-wrap row whose cells are ordered chips. That design is
   more specific than the generic card rules above and it wins, correctly — it
   is the design the owner pointed at when he asked for this.

   What it cannot know is which of its chips is a SENTENCE. Measured at 390:
   "Example Co" sat in a 157px chip beside two others, which is
   the same too-narrow-for-prose the gate condemns everywhere else. The stamper
   already marks any cell over the gate's prose threshold; give those chips the
   whole row and leave every short one exactly where the tidy design put it. */
@media (max-width: 767px) {
  .erpal-app .erpal-listing table tbody td.erpal-td-long {
    flex: 1 1 100%;
    width: 100%;
    min-width: 0;
  }
}

/* ── THE FOLLOW-UP FLAG SITS ABOVE THE TITLE ON A CARD (1.15.3, 2026-09-26) ──
   erpal_crm_ui 1.15.2 put the next-action pill (`.erpal-flag`, "⚑ Nov 11")
   inline in front of a listing's title. On a 390px card the title cell is
   ~285px; the pill takes ~70px of it, so a short deal title such as
   "Riverbend — Nurse-call integration" wrapped onto two lines and /deals and
   /calls on the CRM demo failed the mobile gate's words-per-line rule
   (median 3–3.5 < 4). The pill is a label for the row, not part of the
   sentence: on a card it gets its own line and the title keeps the full
   width. Desktop tables are untouched. */
@media (max-width: 767px) {
  table.erpal-resptable td .erpal-flag,
  .erpal-app .erpal-listing table tbody td .erpal-flag {
    display: flex;
    width: fit-content;
    margin: 0 0 4px 0;
  }
}

/* ── THE BULK CHECKBOX GETS ITS OWN LABELLED ROW ON A CARD (1.15.11) ────────
   The views pilot (2026-09-28) failed the fleet mobile gate on /deals and
   /leads with VBO present. The checkbox cell was a 32px chip sharing the
   headline line, so the title chip lost that width (109px against the 120px
   floor on the pilot's data), and the checkbox sat on the card with no label
   at all.

   On a card the checkbox cell is now a row of its own above the headline:
   full width, a 44px thumb target, and a visible "Select" beside the box. The
   title gets the whole line under it. SCREEN READERS were never the gap: VBO
   gives each row checkbox a visually hidden <label> carrying the record's own
   name ("Deal 04 renewal"), and it stays the accessible name. That label is
   stretched over the whole row, still with its text hidden, so a tap anywhere
   on the "Select" row toggles the box. The phone row-tap handler in
   erpal-listview.js already ignores taps on a <label>, so the tap never opens
   the record.

   Written against both card designs: erpal_tidy's `.erpal-listing` chips,
   which is what the CRM listings draw, and this file's generic card. The
   selectors carry one more type than tidy's (`tr >`), so they win whichever
   stylesheet loads last. */
@media (max-width: 767px) {
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form,
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form {
    order: 0;
    flex: 1 1 100%;
    width: 100%;
    min-width: 0;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: .6rem;
    padding: 0;
    padding-inline-start: 0;
    position: relative;
  }
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form::before,
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form::before { content: none; }
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form::after,
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form::after {
    content: "Select";
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--erpal-muted, #5f6b7a);
  }
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form .js-form-item,
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form .js-form-item {
    display: flex;
    align-items: center;
    margin: 0;
  }
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form input[type="checkbox"],
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form input[type="checkbox"] {
    width: 1.3rem;
    height: 1.3rem;
    margin: 0;
  }
  /* The record-name label, over the whole row. Text still clipped away:
     `font-size: 0` rather than a colour, so no contrast check meets an
     invisible word. */
  .erpal-app .erpal-listing table tbody tr > td.views-field-views-bulk-operations-bulk-form label,
  table.erpal-resptable tbody tr > td.views-field-views-bulk-operations-bulk-form label {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    margin: 0;
    clip: auto;
    clip-path: none;
    overflow: hidden;
    font-size: 0;
    cursor: pointer;
    z-index: 1;
  }
  /* THE ROW ACTIONS TAKE THE WIDTH THEY DRAW. erpal_tidy sizes this cell
     `width: 1%` for the desktop table; on a card that is 1% of the row, 3px
     measured, and its three icons spill `nowrap` past the card's right edge
     the moment the meta line is full. With the checkbox on its own row the
     meta line is fuller, so /deals at 390 showed exactly that. The cell's own
     width lets the flex row wrap it to the next line instead. */
  .erpal-app .erpal-listing table tbody tr > td.erpal-col-actions {
    width: auto;
    flex: 0 0 auto;
    margin-inline-start: auto;
  }
}
