/* D-559 — stacked-card treatment for comparison tables below the `md` breakpoint.
 *
 * WHY THIS FILE EXISTS. A wide table in an `overflow-x-auto` wrapper hides its
 * rightmost columns behind an undiscoverable horizontal swipe. On our corpus
 * those columns are where the prices live: `affordable-answering-service.html`
 * rendered our own `$29` at 0.000 visible ratio behind a 496px hidden scroll.
 * A published price a buyer cannot see is a trust signal that does not exist.
 *
 * The sanctioned remedy used to be `min-w-[600px]` (QA-013) and its CSS twin
 * `@media (max-width: 768px) { .comparison-table { min-width: 800px } }`, which
 * *forced* the very scroll they were meant to relieve — and did so only on
 * phones. Both are retired (see playbooks/design.md § Wide tables on mobile).
 *
 * WHY CSS RATHER THAN A SECOND COPY OF THE MARKUP. The stacked-card remedy can
 * be implemented by duplicating the table into a `md:hidden` card block. That
 * puts every price string on the page twice, and two copies of a price drift.
 * Here one `<table>` stays the single source of truth: below `md` it renders as
 * cards, from `md` up it renders as a table. No price, term, or CTA string is
 * duplicated anywhere.
 *
 * CONTRACT. Apply `stack-table` to a `<table>` whose `<tbody>` rows are the
 * things being compared. Give every `<td>` a `data-label` equal to its column's
 * `<th>` text — that label becomes the cell's key when the row stacks. The first
 * cell becomes the card title. When the first column is a rank (`#`), add
 * `stack-table--rank`: the rank stays a labelled row and the second column
 * (the name) is promoted to the title.
 *
 * The 767px ceiling is Tailwind's `md` breakpoint (768px) minus one, so the
 * card layout and the `md:` utilities on these pages hand off at the same point.
 */

/* ── `fit-table`: the DESKTOP half of the same class ────────────────────────
 * daisyUI ships `.table :where(thead, tfoot) { white-space: nowrap }`. A header
 * that cannot wrap sets each column's minimum width to its header TEXT, so an
 * n-column table can never shrink below the sum of its headers. On
 * `vs/answerfirst.html` those five headers sum to 864px inside a 702px
 * `max-w-3xl` reading column: the table overflows by 161px and `Annual Savings`
 * -- `$1,078-1,293/yr` -- renders at 0.000 visible ratio on a 1280px DESKTOP
 * viewport, where a buyer does the comparison. Stacking below `md` cannot fix
 * that; the header simply has to be allowed to wrap.
 *
 * daisyUI's rule is written with `:where()` (zero specificity), so a single
 * class overrides it. This is a layout change only: no cell text is touched. */
.fit-table {
  table-layout: fixed;
}

.fit-table th,
.fit-table td {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Some table values combine an icon with text. Keep that content as one layout
   item so the mobile grid cannot auto-place the icon in column two and wrap its
   text back underneath the label in column one. `display: contents` preserves
   the table's desktop rendering; the mobile rule below turns it into one item. */
.stack-table__value {
  display: contents;
}

@media (max-width: 767px) {
  .stack-table,
  .stack-table tbody,
  .stack-table tr,
  .stack-table td {
    display: block;
    width: 100%;
  }

  /* Column headers become each cell's `data-label`, so the visually rendered
     header row is redundant. Keep it in the accessibility tree rather than
     `display: none`, which would remove it from screen readers too.
     Positioned off-screen rather than clipped with the usual
     `overflow: hidden; clip: rect(0,0,0,0)` recipe: an `overflow-x` other than
     `visible` on a box narrower than its content is precisely the signature of
     an undiscoverable horizontal swipe, so the sr-only header would trip the
     D-556 geometry guard on every page it appears. Overflow to the LEFT of the
     origin never creates a scrollbar, so this hides without clipping. */
  .stack-table thead {
    position: absolute;
    left: -10000px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: visible;
  }

  /* `overflow: hidden` here (to clip the corners) would clip the off-screen
     header row too, re-creating the same false signal. `tbody`-scoped. */
  .stack-table tbody tr {
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 0.75rem;
    margin-bottom: 0.75rem;
    padding: 0.25rem 0.875rem 0.625rem;
  }

  /* Two tracks, not a flex row. A flex `::before` with `flex: 0 1 auto` shrinks
     below its own min-content when the value is a long string, and the label
     then overlaps the value ("IncludedOverflow coverage and emergency..."). Grid
     tracks cannot collapse into one another. Both tracks are `minmax(0, ...)` so
     either side wraps instead of overflowing its column. Every <td> in the
     transformed corpus has exactly one significant child node, so the value is
     always a single grid item in track 2. */
  .stack-table td {
    display: grid;
    grid-template-columns: minmax(0, 38%) minmax(0, 1fr);
    column-gap: 0.75rem;
    align-items: baseline;
    padding: 0.5rem 0;
    border: 0;
    text-align: left;
    /* `whitespace-nowrap` on a price cell is what pushes a table past the
       viewport. Inside a card there is nothing to push against, so let it wrap. */
    white-space: normal;
  }

  .stack-table td + td {
    border-top: 1px solid rgba(0, 0, 0, 0.06);
  }

  /* The label must NOT inherit the value's colour. On features.html a "no" cell
     is `text-base-content/30`; an inherited 30% alpha multiplied by an 0.65
     opacity put the vendor's name near 20% -- unreadable, and a contrast defect
     this change would have introduced. `--bc` is daisyUI's theme-aware
     base-content token, so this stays correct in dark mode. */
  .stack-table td::before {
    content: attr(data-label);
    font-weight: 600;
    color: oklch(var(--bc) / 0.65);
  }

  /* The value side may be a long string ("Published plan features + $0.29/call
     overage"); let it wrap inside its track rather than overflow it. */
  .stack-table td > * {
    min-width: 0;
  }

  .stack-table td > .stack-table__value {
    display: block;
    grid-column: 2;
    min-width: 0;
  }

  /* Card title: the first cell, or the second when the first is a rank. */
  .stack-table td:first-child {
    display: block;
    padding-top: 0.75rem;
    font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
    font-weight: 700;
    font-size: 1rem;
  }

  .stack-table td:first-child::before {
    content: none;
  }

  .stack-table--rank tbody tr {
    display: flex;
    flex-direction: column;
  }

  .stack-table--rank td:first-child {
    display: grid;
    padding-top: 0.5rem;
    font-family: inherit;
    font-weight: 400;
    font-size: 0.875rem;
  }

  .stack-table--rank td:first-child::before {
    content: attr(data-label);
    font-weight: 600;
    color: oklch(var(--bc) / 0.65);
  }

  /* Promote the name above the rank without reordering the source. */
  .stack-table--rank td:nth-child(2) {
    order: -1;
    display: block;
    padding-top: 0.75rem;
    border-top: 0;
    font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
    font-weight: 700;
    font-size: 1rem;
  }

  .stack-table--rank td:nth-child(2)::before {
    content: none;
  }

  /* `divide-y` on the tbody would draw a rule between cards on top of the card
     borders themselves. The per-cell `td + td` rule already separates values. */
  .stack-table tbody > :not([hidden]) ~ :not([hidden]) {
    border-top-width: 0;
  }
}
