/* ==========================================================================
   Portal responsive table system
   ==========================================================================

   One contract for every portal table. A normal portal page must never need
   horizontal scrolling to read a table, so this system has no `overflow-x`
   escape hatch and sets no table `min-width`. When the columns stop fitting,
   information is progressively reorganised instead of pushed off-screen.

   USAGE
   -----
       <div class="ptbl">
         <table class="ptbl-table ptbl-stack">
           <thead>
             <tr>
               <th class="table-col-product">Product</th>
               <th class="table-col-money">GP / unit</th>
               <th class="table-col-status ptbl-prio-2">Economics</th>
               <th class="table-col-detail ptbl-prio-3">Why</th>
             </tr>
           </thead>
           <tbody>
             <tr>
               <td class="table-col-product" data-label="Product">
                 Klavox 1Gm 14 Tab
                 <span class="ptbl-sub">SKU 1782</span>
                 <span class="ptbl-fold">Confirmed &middot; Already buys</span>
               </td>
               <td class="table-col-money" data-label="GP / unit">32.2501</td>
               ...
             </tr>
           </tbody>
         </table>
       </div>

   COLUMN TYPE -- width follows content type, never an equal split.

   FLEXIBLE (never `width:1%`; they absorb the spare width and keep a floor):
       .table-col-product   the primary text column: product / group names
       .table-col-detail    explanations, comments, recommendations
       .table-col-group     grouped planning content (several labelled values)

   COMPACT (`width:1%`, collapse to their own content):
       .table-col-number    content width, tabular, end-aligned
       .table-col-money     as number, plus tabular numerals
       .table-col-percent   as number
       .table-col-status    pill sized
       .table-col-action    buttons / links
       .table-col-check     a single control

   Compact columns are laid out at `width:1%` under `table-layout:auto`, which
   collapses them to their content and hands every remaining pixel to the
   flexible columns. That is what stops one long text column from shoving the
   numbers off-screen, without giving every column the same width.

   The flexible columns carry a `min-inline-size` floor and break on word
   boundaries only. Without the floor, enough compact columns can squeeze a
   text column past its shortest word and render a product name one or two
   characters per line - technically fitting, and unreadable. Reaching that
   floor is the signal to drop a priority-2/3 column, never to shred a word.

   PRIORITY -- what survives as the viewport narrows.
       (no class)    priority 1: essential decision data, always visible
       .ptbl-prio-2  hidden below 1120px; fold it into the primary cell
       .ptbl-prio-3  hidden below 1400px; fold it or move it to a detail area

   FOLDING -- restating a dropped column inside the primary cell.
       .ptbl-fold     appears only once priority-2 columns are hidden
       .ptbl-fold-3   appears only once priority-3 columns are hidden
       .ptbl-sub      secondary metadata (SKU, code), always visible

   STACKED -- below 640px a row becomes a block. Every `td` needs `data-label`,
   which is rendered as its own caption. Add `.ptbl-stack` to the table to opt
   in; a table that reads badly when stacked can simply leave it off.

   RTL is handled with logical properties, so no direction override is needed.
   ========================================================================== */

.ptbl {
    /* Deliberately no overflow-x. If a table does not fit, reorganise it. */
    width: 100%;
    max-width: 100%;
}

.ptbl-table {
    width: 100%;
    max-width: 100%;
    table-layout: auto;
    border-collapse: separate;
    border-spacing: 0;
}

/* Headers may wrap onto two lines rather than force the table wider. */
.ptbl-table th {
    white-space: normal;
    overflow-wrap: break-word;
    text-align: start;
    vertical-align: bottom;
}

.ptbl-table td {
    text-align: start;
    vertical-align: middle;
    overflow-wrap: break-word;
}

/* --------------------------------------------------------------- columns */

/* Flexible: takes the width the compact columns do not need.
   Words break on word boundaries; only a single unbroken token longer than the
   column (a code, a URL) is broken, and `break-word` does that without
   shredding ordinary words the way `anywhere` / `break-all` would. */
.ptbl-table .table-col-product,
.ptbl-table .table-col-detail,
.ptbl-table .table-col-group {
    width: auto;
    white-space: normal;
    word-break: normal;
    overflow-wrap: break-word;
    hyphens: none;
}

/* The product column is the one that should grow first. */
.ptbl-table .table-col-product {
    min-inline-size: 11rem;
    max-width: 24rem;
}

.ptbl-table .table-col-detail {
    font-size: .78rem;
    line-height: 1.4;
    min-inline-size: 9rem;
    max-width: 20rem;
}

/* Several labelled values sharing one column still need room to read. */
.ptbl-table .table-col-group {
    min-inline-size: 10rem;
}

/* Compact: collapse to content, never share width equally.
   Only genuinely short values belong here. A text column listed above must
   never be given `width:1%`. */
.ptbl-table .table-col-number,
.ptbl-table .table-col-money,
.ptbl-table .table-col-percent,
.ptbl-table .table-col-status,
.ptbl-table .table-col-action,
.ptbl-table .table-col-check {
    width: 1%;
    white-space: nowrap;
}

.ptbl-table .table-col-number,
.ptbl-table .table-col-money,
.ptbl-table .table-col-percent {
    text-align: end;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.ptbl-table .table-col-status,
.ptbl-table .table-col-action,
.ptbl-table .table-col-check {
    text-align: start;
}

.ptbl-table .table-col-check {
    width: 2.4rem;
}

/* A numeric cell may still carry a wrapping caption beneath its figure.
   It wraps by word, so the column sizes to the caption's longest word - not to
   its longest letter, which is what produced one-character-wide columns. */
.ptbl-table .table-col-number .ptbl-sub,
.ptbl-table .table-col-money .ptbl-sub,
.ptbl-table .table-col-percent .ptbl-sub,
.ptbl-table .table-col-status .ptbl-sub {
    white-space: normal;
    word-break: normal;
    overflow-wrap: break-word;
}

/* Headers wrap by word too, and never character-by-character. */
.ptbl-table th {
    word-break: normal;
    hyphens: none;
}

/* ------------------------------------------------------- cell composition */

/* Secondary metadata under a primary value: SKU, code, unit, qualifier. */
.ptbl-sub {
    display: block;
    font-size: .7rem;
    font-weight: 600;
    line-height: 1.3;
    opacity: .72;
    word-break: normal;
    overflow-wrap: break-word;
}

/* Folded content is dormant until its column is actually dropped. */
.ptbl-fold,
.ptbl-fold-3 {
    display: none;
    font-size: .7rem;
    font-weight: 600;
    line-height: 1.35;
    opacity: .8;
    margin-top: .2rem;
}

/* Inputs in a compact cell size to the cell, not to a fixed pixel width. */
.ptbl-table .table-col-number input,
.ptbl-table .table-col-money input,
.ptbl-table .table-col-percent input,
.ptbl-table .table-col-action select,
.ptbl-table .table-col-status select {
    width: 100%;
    min-width: 4.5rem;
    max-width: 7.5rem;
}

/* ------------------------------------------------------------- priorities */

/* Priority 3 goes first: deep diagnostics nobody decides on at this width. */
@media (max-width: 1399px) {
    .ptbl-table .ptbl-prio-3 { display: none; }
    .ptbl-table .ptbl-fold-3 { display: block; }
}

/* Priority 2 next: supporting figures that fold into the primary cell. */
@media (max-width: 1119px) {
    .ptbl-table .ptbl-prio-2 { display: none; }
    .ptbl-table .ptbl-fold { display: block; }
}

@media (max-width: 860px) {
    .ptbl-table th,
    .ptbl-table td { padding-inline: .5rem; }
    .ptbl-table .table-col-product { min-inline-size: 9rem; max-width: 14rem; }
    .ptbl-table .table-col-detail { min-inline-size: 8rem; }
    .ptbl-table .table-col-group { min-inline-size: 8rem; }
}

/* ------------------------------------------------ wide analysis shell */

/* Analysis pages (Profit Steering diagnostics) opt into a wider page shell.
   The extra width belongs to the column that reads as prose: a product name is
   the only cell here that benefits from more room, while every figure is
   already at its content width. Status columns get a floor so a pill never
   wraps mid-word. Nothing below sets a table min-width or an overflow, so the
   contract is unchanged - only the share of the spare width. */
.ps-shell-wide .ptbl-table .table-col-product {
    min-inline-size: 15rem;
    max-width: 32rem;
}

.ps-shell-wide .ptbl-table .table-col-detail {
    min-inline-size: 11rem;
    max-width: 26rem;
}

.ps-shell-wide .ptbl-table .table-col-status {
    min-inline-size: 6rem;
}

/* ---------------------------------------------------------------- stacked */

/* Below 640px a row becomes a block. Semantics are untouched: this is CSS
   layout only, so the table still reads correctly to assistive technology. */
@media (max-width: 639px) {
    .ptbl-stack thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .ptbl-stack tbody tr { display: block; padding: .35rem 0; }

    .ptbl-stack tbody td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
        width: auto !important;
        white-space: normal;
        text-align: start;
        border-bottom: 0;
        padding-block: .3rem;
    }

    .ptbl-stack tbody td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: .66rem;
        font-weight: 800;
        letter-spacing: .06em;
        text-transform: uppercase;
        opacity: .7;
    }

    /* A cell with no caption, and the leading product cell, span the block. */
    .ptbl-stack tbody td:not([data-label])::before { content: none; }

    .ptbl-stack tbody td.table-col-product {
        display: block;
        font-weight: 700;
        padding-top: .55rem;
    }

    .ptbl-stack tbody td.table-col-product::before { content: none; }

    .ptbl-stack tbody tr + tr {
        border-top: 1px solid rgba(0, 0, 0, .1);
    }

    .ptbl-stack tfoot td { display: block; width: auto !important; }
}

/* ==========================================================================
   Pending purchase-order (PDF) mapping queue
   ==========================================================================

   A CSS grid rather than a table: rows are swapped in one at a time over
   HTMX, and HtmlMinifyMiddleware discards bare <tr> fragments. Same reason
   the OPS order-line partial is div-based.

   The list has no scroll container of its own. It grows with its content and
   the page scrolls; the six columns are sized so they fit without horizontal
   scrolling, and below 900px each row becomes a captioned card.
   ========================================================================== */

.pdf-queue { --pdf-queue-cols: 9rem 1fr 4rem 10rem 8rem 16rem; }

.pdf-queue-head,
.pdf-queue-row {
    display: grid;
    grid-template-columns: var(--pdf-queue-cols);
    gap: .75rem;
    align-items: start;
    padding: .6rem .75rem;
}

.pdf-queue-head {
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    opacity: .65;
    border-bottom: 1px solid var(--hmc-brand-border, #dfe7e2);
}

.pdf-queue-row + .pdf-queue-row { border-top: 1px solid #eef1ee; }
.pdf-queue-row { font-size: .82rem; }

/* Codes are barcode-length and carry no spaces, so they need an explicit
   break opportunity or one row sets the width of the whole list. */
.pdf-queue-cell { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.pdf-queue-code { font-weight: 700; }
.pdf-queue-qty { white-space: nowrap; }

.pdf-queue-source { line-height: 1.35; }
.pdf-queue-source__order { display: block; font-weight: 700; }
.pdf-queue-source__meta { display: block; font-size: .72rem; opacity: .7; }

.pdf-queue-badge {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.pdf-queue-badge[data-status="UNMAPPED"] { background: #fdf1dc; color: #8a5a11; }
.pdf-queue-badge[data-status="ADDED"] { background: #e7f5ec; color: #1c6b3d; }
.pdf-queue-badge[data-status="LOCKED"] { background: #eef1f4; color: #44515e; }
.pdf-queue-badge[data-status="IGNORED"] { background: #eef1f4; color: #5b6570; }
.pdf-queue-badge[data-status="NOT_MAPPABLE"] { background: #f3e8f0; color: #7a2a5f; }
.pdf-queue-badge[data-status="OTHER"] { background: #eef1f4; color: #44515e; }

.pdf-queue-flash {
    display: block;
    margin-block-start: 4px;
    font-size: .72rem;
    font-weight: 600;
}

.pdf-queue-flash[data-tone="ok"] { color: #1c6b3d; }
.pdf-queue-flash[data-tone="warn"] { color: #8a5a11; }
.pdf-queue-flash[data-tone="error"] { color: #9b2226; }

.pdf-queue-form { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.pdf-queue-lookup { position: relative; flex: 1 1 8rem; min-width: 7rem; }

.pdf-queue-search,
.pdf-queue-uom {
    width: 100%;
    min-height: 34px;
    border-radius: .6rem;
    border: 1px solid var(--hmc-brand-border, #dfe7e2);
    font-size: .78rem;
    padding-inline: .5rem;
}

.pdf-queue-uom { width: 4.5rem; flex: 0 0 auto; }
.pdf-queue-map-btn { padding: .3rem .8rem; font-size: .78rem; }

/* Secondary actions stay out of the way until asked for. */
.pdf-queue-more { margin-block-start: .4rem; }
.pdf-queue-more > summary {
    cursor: pointer;
    font-size: .72rem;
    font-weight: 700;
    opacity: .75;
}
.pdf-queue-more__body {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin-block-start: .4rem;
}

.pdf-queue-link-btn {
    background: none;
    border: 0;
    padding: 0;
    font-size: .76rem;
    font-weight: 700;
    text-align: start;
    text-decoration: underline;
    cursor: pointer;
    color: #44515e;
}

.pdf-queue-link-btn--danger { color: #9b2226; }
.pdf-queue-link-btn[disabled] { opacity: .5; cursor: progress; }

.pdf-queue-hint { display: block; font-size: .7rem; opacity: .7; }

/* A resolved row states its outcome, then leaves. */
.pdf-queue-row--resolved { grid-template-columns: 1fr; }
.pdf-queue-row--leaving { opacity: 0; transition: opacity 300ms ease; }

/* Captions are only meaningful once the grid stacks. */
.pdf-queue-cell::before { content: none; }

@media (max-width: 899.98px) {
    /* One card per row: the header is dropped and each value states its own
       caption, so nothing is clipped and the page never scrolls sideways. */
    .pdf-queue-head { display: none; }
    .pdf-queue-row { grid-template-columns: 1fr; gap: .35rem; padding: .75rem; }

    .pdf-queue-cell[data-label] {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
        text-align: end;
    }

    .pdf-queue-cell[data-label]::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: .64rem;
        font-weight: 800;
        letter-spacing: .06em;
        text-transform: uppercase;
        opacity: .65;
        text-align: start;
    }

    /* The action cell is a control block, not a caption/value pair. */
    .pdf-queue-cell.pdf-queue-action { display: block; text-align: start; }
    .pdf-queue-cell.pdf-queue-action::before { content: none; }
    /* Multi-value cells: the caption sits in its own column spanning the
       whole cell, so the values stack instead of splitting the width and
       breaking mid-word. */
    .pdf-queue-cell.pdf-queue-source,
    .pdf-queue-cell.pdf-queue-status {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: baseline;
        column-gap: 1rem;
        row-gap: .1rem;
        text-align: end;
    }

    .pdf-queue-cell.pdf-queue-source::before,
    .pdf-queue-cell.pdf-queue-status::before {
        grid-column: 1;
        grid-row: 1 / -1;
    }

    .pdf-queue-cell.pdf-queue-source > *,
    .pdf-queue-cell.pdf-queue-status > * {
        grid-column: 2;
        justify-self: end;
        text-align: end;
    }

    .pdf-queue-lookup { flex: 1 1 100%; }
    .pdf-queue-uom { width: 5.5rem; }
    .pdf-queue-search,
    .pdf-queue-uom { min-height: 44px; font-size: .85rem; }
    .pdf-queue-map-btn { min-height: 44px; flex: 1 1 auto; }
    .pdf-queue-link-btn { min-height: 44px; }
    /* The disclosure is the only way to reach Ignore / Not mappable on a
       phone, so it gets a real touch target too. */
    .pdf-queue-more > summary {
        min-height: 44px;
        padding-block: .85rem;
    }
}
