/* =====================================================================
   appTable — the iOS 26 list on phones
   ---------------------------------------------------------------------
   Pairs with assets/js/apptable-mobile.js, which puts `nzm-on` on <html>
   below 800px, `nzm-table` on every table it drives and `nzm-planned` on
   the ones whose three row elements it has chosen. Nothing here applies
   on a desktop, and nothing here applies to a table the JS left alone —
   that table keeps the normal appTable skin.

   The row is a CSS grid, not a table row:

       col 1        col 2                     col 3       col 4
     +---------+-------------------------+-----------+---------+
     |         | title            (row1) |           |         |
     |  thumb  |-------------------------|  trailing |    >    |
     |         | subtitle         (row2) |           |         |
     +---------+-------------------------+-----------+---------+

   The cells are still real <td>s inside the real <tr> — the layout moves
   them, it does not rebuild them — so every row handler appTable binds on
   the table (delete, undo, batch selection, the ajax modals) keeps
   working. See the header of the JS file for why that mattered.

   Colours are the shared --ios26-* tokens declared in app.all.css, which
   body.color-1E202D re-declares, so dark mode needs no duplicated rules
   here. The exceptions carry a body.color-1E202D prefix + !important
   because assets/css/color/1E202D.css is injected at RUNTIME and wins
   every tie (see .claude/rules/frontend-ui.md).
   ===================================================================== */

/* ================================================ the scrolling frame */

/* On a phone the LIST is the page. The desktop skin puts the rows in
   their own scroll box (for the sticky header and the frozen action
   column, neither of which exists here) and that box has an inline
   max-height from apptable-sticky.js — hence !important. */
html.nzm-on .dt-container .dtg-hscroll,
html.nzm-on .table-responsive:has(> .dt-container) {
    max-height: none !important;
    height: auto !important;
    overflow: visible !important;
}

/* ======================================================== the table */

html.nzm-on .dt-container table.dataTable.nzm-table {
    display: block;
    width: 100% !important;
    border: 0;
    background: transparent;
}

html.nzm-on .dt-container table.dataTable.nzm-table > thead {
    display: none; /* replaced by the sort control below */
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody {
    display: block;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tfoot {
    display: block;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tfoot > tr {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tfoot > tr > th,
html.nzm-on .dt-container table.dataTable.nzm-table > tfoot > tr > td {
    display: block;
    position: static !important;
    border: 0;
    padding: 0;
    box-shadow: none;
}

/* the empty-table message keeps its own row */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr:not(.nzm-row):not(.child) {
    display: block;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr > td.dt-empty {
    display: block;
    padding: 34px 16px;
    text-align: center;
    color: var(--ios26-muted);
}

/* ========================================================== the row */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;

    min-height: 56px;
    padding: 11px 16px;

    background: transparent;

    /* app.all.css carries `.dataTable:not(.js-selection-mode) tbody tr
       { border-color: #f1f1f5 !important }` — a light hairline that stays
       light in dark mode unless this shouts back. */
    border-bottom: 1px solid var(--ios26-hairline) !important;
    box-shadow: none;

    -webkit-tap-highlight-color: transparent;
    transition: background-color 0.18s var(--ios26-ease);
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row:last-child {
    border-bottom: 0 !important;
}

/* the press state IS the affordance on a touch screen */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row:active {
    background: var(--ios26-fill);
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row.dtr-expanded {
    background: var(--ios26-fill);
    border-bottom-color: transparent !important;
}

/* the desktop skin's stripes, hover tint and frozen last column have no
   place in a list */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr > td,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr > th {
    position: static !important;
    background: transparent !important;
    box-shadow: none !important;
    border: 0 !important;
    border-radius: 0 !important;

    /* The desktop skin sets the cell padding with !important (app.all.css
       does too, which is why it has to) — the row owns its padding here, so
       this has to shout back. */
    padding: 0 !important;

    /* The column width utilities (.w200, .w15p, .w50 …) are still on these
       cells and a grid item honours its own width — one 15% cell wrapping a
       job title one CHARACTER per line is what that looks like. */
    width: auto !important;
    min-width: 0;
    max-width: none;
    vertical-align: middle;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td {
    display: block;
    overflow: hidden;
}

/* --- the three elements ------------------------------------------- */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell {
    grid-column: 2;
    grid-row: 1;

    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--ios26-text);

    /* One line, ellipsised — a wrapping title turns the list into a wall.
       !important because app.all.css forces `white-space: normal` on every
       cell of a `.nowrap` table inside its own mobile media query. */
    white-space: nowrap !important;
    text-overflow: ellipsis;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-sub-cell {
    grid-column: 2;
    grid-row: 2;

    margin-top: 2px;
    font-size: 13px;
    line-height: 1.35;
    color: var(--ios26-muted);

    white-space: nowrap !important;
    text-overflow: ellipsis;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-trail-cell {
    grid-column: 3;
    grid-row: 1 / span 2;

    margin-left: 12px;
    text-align: right;
    font-size: 14px;
    line-height: 1.3;
    color: var(--ios26-muted);
    white-space: nowrap !important;
}

/* --- one line, always -------------------------------------------- */
/* `white-space: nowrap` alone does NOT hold a title to one line: a <br> in
   the cell breaks anyway, and a block-level child (a <div> wrapper, a <ul>
   of labels) opens a new line box of its own. A row title that grows to
   three lines is a row that has stopped being a list item, so both are
   closed off here and the overflow is ellipsised instead. */

/* `display: none` is the only value that reliably stops a <br> breaking —
   inline / inline-block still break in Chrome (measured). It runs the two
   words together, so apptable-mobile.js swaps the <br>s for spaces first
   and this is the backstop for any cell it did not reach. */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell br,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-sub-cell br {
    display: none;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell :is(div, p, ul, ol, li, h1, h2, h3, h4, h5, h6),
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-sub-cell :is(div, p, ul, ol, li, h1, h2, h3, h4, h5, h6) {
    display: inline;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* a child with a white-space rule of its own would escape the cell's */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell *,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-sub-cell * {
    white-space: inherit;
}

/* Anything else that survived — nothing should, but a stray visible cell
   would break the "three elements" rule the whole design rests on. Only
   applied once the JS has actually chosen the three. */
html.nzm-on .dt-container table.dataTable.nzm-table.nzm-planned > tbody > tr.nzm-row > td:not(.nzm-title-cell):not(.nzm-sub-cell):not(.nzm-trail-cell):not(.nzm-media-cell) {
    display: none;
}

/* --- the 1:1 thumbnail -------------------------------------------- */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > .nzm-media,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-media-cell {
    grid-column: 1;
    grid-row: 1 / span 2;

    display: block;
    width: 40px !important;
    height: 40px;
    margin-right: 12px;
    flex: none;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > .nzm-media .avatar,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-media-cell .avatar {
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > .nzm-media img,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-media-cell img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 10px;
}

/* --- the disclosure chevron --------------------------------------- */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row::after {
    content: "";
    grid-column: 4;
    grid-row: 1 / span 2;

    width: 7px;
    height: 7px;
    margin-left: 12px;

    border-right: 2px solid var(--ios26-muted);
    border-bottom: 2px solid var(--ios26-muted);
    opacity: 0.55;
    border-radius: 1px;

    justify-self: end;
    align-self: center;
    transform: rotate(-45deg);
    transition: transform 0.28s var(--ios26-ease);
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row.dtr-expanded::after {
    transform: rotate(45deg);
}

/* --- links inside a collapsed row ---------------------------------- */
/* The ROW is the tap target. A live link inside it would navigate and
   open the card on the same tap, so the links go quiet here and come
   back alive inside the card (and in the title of the card). Compact
   rows are the exception: their whole card IS the link to the record. */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row:not(.nzm-compact) > td a {
    pointer-events: none;
    color: inherit;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell a {
    color: var(--ios26-text);
}

/* --- rows the server already built as a mobile card ---------------- */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact {
    grid-template-columns: minmax(0, 1fr) auto;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact > td {
    grid-column: 1;
    grid-row: 1;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact::after {
    grid-column: 2;
    grid-row: 1;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact .box-wrapper,
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact .box-label {
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
}

/* Same rule for the rows the server composed: every line of its card is one
   line. `.truncate-ellipsis` (app.all.css) already does this for the titles
   that were built with it — this covers the lines that were not, so no card
   line can wrap whatever the record is called. */
html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact .box-label > * > * {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-compact .box-label br {
    display: none;
}

/* --- batch selection ---------------------------------------------- */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row.batch-operation-selected {
    background: var(--ios26-accent-soft);
}

/* ==================================================== the open card */

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.child {
    display: block;
    background: transparent;
}

html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.child > td {
    display: block;
    position: relative !important;
    padding: 0 !important;
    border: 0 !important;
    background: transparent !important;
}

html.nzm-on .nzm-card {
    margin: 0 16px 14px;
    border: 1px solid var(--ios26-hairline);
    border-radius: var(--ios26-radius-lg);
    background: var(--ios26-surface-strong);
    box-shadow: var(--ios26-shadow-1);
    animation: nzm-card-in 0.24s var(--ios26-ease) both;
}

@keyframes nzm-card-in {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

html.nzm-on .nzm-card-title {
    padding: 13px 16px 12px;
    font-size: 17px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--ios26-text);
}

html.nzm-on .nzm-card-title a {
    color: var(--ios26-accent);
}

html.nzm-on .nzm-fields {
    list-style: none;
    margin: 0;
    padding: 0;
}

html.nzm-on .nzm-fields > li {
    display: flex;
    align-items: baseline;
    gap: 16px;
    padding: 10px 16px;
    border-top: 1px solid var(--ios26-hairline);
    font-size: 14px;
}

html.nzm-on .nzm-fields > li.nzm-nolabel,
html.nzm-on .nzm-fields > li.nzm-long {
    display: block;
}

html.nzm-on .nzm-fields > li.nzm-long .nzm-k {
    display: block;
    margin-bottom: 3px;
}

html.nzm-on .nzm-k {
    flex: 0 0 38%;
    color: var(--ios26-muted);
    font-size: 13px;
    line-height: 1.4;
}

html.nzm-on .nzm-v {
    flex: 1 1 auto;
    min-width: 0;
    text-align: right;
    line-height: 1.4;
    color: var(--ios26-text);
    overflow-wrap: anywhere;
}

html.nzm-on .nzm-fields > li.nzm-nolabel .nzm-v,
html.nzm-on .nzm-fields > li.nzm-long .nzm-v {
    display: block;
    text-align: left;
}

html.nzm-on .nzm-v ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* --- the row's own buttons ----------------------------------------- */

html.nzm-on .nzm-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--ios26-hairline);
}

html.nzm-on .nzm-actions .dropdown {
    display: inline-flex;
}

html.nzm-on .nzm-actions a,
html.nzm-on .nzm-actions .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;

    /* 44px is the iOS minimum for anything a finger has to hit */
    min-width: 44px;
    min-height: 44px;
    margin: 0;
    padding: 0 15px;

    border: 1px solid var(--ios26-edge);
    border-radius: var(--ios26-pill);
    background: var(--ios26-surface);
    color: var(--ios26-text);
    font-size: 14px;
    line-height: 1;
    text-decoration: none;
}

html.nzm-on .nzm-actions a:active,
html.nzm-on .nzm-actions .btn:active {
    background: var(--ios26-fill-hover);
}

html.nzm-on .nzm-actions a.delete,
html.nzm-on .nzm-actions a[data-action="delete-confirmation"] {
    color: #ff3b30;
}

/* dropdown menus have to escape the card, not scroll inside it */
html.nzm-on .nzm-card .dropdown-menu {
    z-index: 1080;
}

/* ===================================================== the sort bar */

/* The column headers are gone, so this is the only sort control left.
   It reads as the iOS list-sort button: the current field, a chevron,
   and a menu of every sortable column. */

html.nzm-on .dt-container .nzm-sortbar {
    display: flex;
    justify-content: flex-end;
    padding: 0 10px 6px;
}

html.nzm-on .dt-container .nzm-sort-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;

    /* 44, not 38: this control only exists on touch, which is exactly
       where the iOS minimum applies. The dashboard's thumb-reachability
       test caught it at 72x38. */
    min-height: 44px;
    padding: 0 10px;

    border: 0;
    border-radius: var(--ios26-radius-sm);
    background: transparent;

    /* NOT --ios26-accent: that token is picked to sit calmly behind
       content, and as 15px text it measures 3.03:1 on the light card and
       3.31:1 on the dark one. These are the same readable pair the
       dashboard uses for .text-primary. */
    color: #2f5fd0;
    font-size: 15px;
    font-weight: 500;
}

body.color-1E202D .dt-container .nzm-sort-btn {
    color: #a6bcff;
}

html.nzm-on .dt-container .nzm-sort-btn:active {
    background: var(--ios26-fill);
}

html.nzm-on .dt-container .nzm-sort-caret {
    font-size: 11px;
    transition: transform 0.2s var(--ios26-ease);
}

html.nzm-on .dt-container .nzm-sort-btn.nzm-desc .nzm-sort-caret {
    transform: rotate(180deg);
}

html.nzm-on .nzm-sort-menu {
    min-width: 220px;
    border-radius: var(--ios26-radius);
}

html.nzm-on .nzm-sort-menu .dropdown-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    min-height: 44px;
}

html.nzm-on .nzm-sort-menu .nzm-sort-dir {
    opacity: 0;
    font-size: 12px;
    transition: transform 0.2s var(--ios26-ease);
}

html.nzm-on .nzm-sort-menu .dropdown-item.active {
    background: transparent;
    color: var(--ios26-accent);
    font-weight: 600;
}

html.nzm-on .nzm-sort-menu .dropdown-item.active .nzm-sort-dir {
    opacity: 1;
}

html.nzm-on .nzm-sort-menu .nzm-sort-dir.nzm-desc {
    transform: rotate(180deg);
}

/* ============================================================== RTL */

html.nzm-on[dir="rtl"] .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row::after,
html.nzm-on body.rtl .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row::after {
    transform: rotate(135deg);
    margin-left: 0;
    margin-right: 12px;
}

html.nzm-on[dir="rtl"] .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row.dtr-expanded::after,
html.nzm-on body.rtl .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row.dtr-expanded::after {
    transform: rotate(45deg);
}

html.nzm-on[dir="rtl"] .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-trail-cell,
html.nzm-on body.rtl .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-trail-cell {
    text-align: left;
    margin-left: 0;
    margin-right: 12px;
}

html.nzm-on[dir="rtl"] .nzm-v,
html.nzm-on body.rtl .nzm-v {
    text-align: left;
}

/* ======================================================= dark theme */

/* assets/css/color/1E202D.css is injected at runtime and wins every tie,
   so the handful of properties it names explicitly need !important here.
   Everything else rides on the --ios26-* tokens, which that file already
   re-declares for dark. */

body.color-1E202D .nzm-card {
    background: rgba(44, 48, 58, 0.92) !important;
    border-color: var(--ios26-hairline) !important;
}

body.color-1E202D .nzm-actions a,
body.color-1E202D .nzm-actions .btn {
    background: rgba(255, 255, 255, 0.06) !important;
    border-color: var(--ios26-edge) !important;
    color: var(--ios26-text) !important;
}

body.color-1E202D .nzm-actions a.delete,
body.color-1E202D .nzm-actions a[data-action="delete-confirmation"] {
    color: #ff6961 !important;
}

body.color-1E202D .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell,
body.color-1E202D .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row > td.nzm-title-cell a,
body.color-1E202D .nzm-card-title,
body.color-1E202D .nzm-v {
    color: var(--ios26-text) !important;
}

body.color-1E202D .nzm-card-title a {
    color: var(--ios26-accent) !important;
}

/* ================================================== reduced motion */

@media (prefers-reduced-motion: reduce) {

    html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row,
    html.nzm-on .dt-container table.dataTable.nzm-table > tbody > tr.nzm-row::after,
    html.nzm-on .dt-container .nzm-sort-caret,
    html.nzm-on .nzm-sort-menu .nzm-sort-dir {
        transition: none;
    }

    html.nzm-on .nzm-card {
        animation: none;
    }
}
