.tt-table {
    width: 100%;
    color: var(--text-color);
    border-collapse: collapse;
}

.tt-table {
    /* Padding */
    --tt-table-padding-header: var(--step--2) var(--step--4);
    --tt-table-padding-body: var(--step--2) var(--step--4);
    --tt-table-padding-footer: var(--step--2) var(--step--2);
    /* Compact */
    --tt-table-padding-compact-header: var(--step--3) var(--step--3);
    --tt-table-padding-compact-body: var(--step--4) var(--step--4);
    --tt-table-padding-compact-footer: var(--step--3) var(--step--3);
    /* super compact */
    --tt-table-padding-super-compact-header: var(--step--5) var(--step--5);
    --tt-table-padding-super-compact-body: var(--step--7) var(--step--7);
    --tt-table-padding-super-compact-footer: var(--step--5) var(--step--5);

    /* Dividers */
    --tt-table-divider-header: var(--border-thin) solid var(--border-muted, #cfcfcf);
    --tt-table-divider-body: var(--border-thin) solid var(--bg-muted);
    --tt-table-divider-footer: var(--border-thin) solid var(--border-muted, #cfcfcf);
    --tt-table-outer-border: var(--border-thin) solid var(--border-muted, #cfcfcf);
}

/* HEADER (THEAD) */
.tt-table thead th {
    padding: var(--tt-table-padding-header);
    border-bottom: var(--tt-table-divider-header);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
}

/* BODY (TBODY) */
.tt-table tbody tr {
    border-bottom: var(--tt-table-divider-body);
}
.tt-table tbody td {
    padding: var(--tt-table-padding-body);
}

/* FOOTER (TFOOT) */
.tt-table tfoot td {
    padding: var(--tt-table-padding-footer);
    border-top: var(--tt-table-divider-footer);
    font-weight: var(--font-weight-semibold);
}

/* DIVIDERS */
.tt-table--strong-dividers {
    --tt-table-divider-header: 1px solid var(--text-color);
    --tt-table-divider-body: 1px solid var(--border-muted, #cfcfcf);
    --tt-table-divider-footer: 1px solid var(--text-color);
    --tt-table-outer-border: var(--border-thin) solid var(--text-color);
}

/* GROUPED ROWS
   For a table whose rows come in blocks under a heading row - a preview of per
   diems gathered under the job that claimed them, say - with one tbody per block
   and the heading as a single colspan cell.

   The heading carries what the rows would otherwise repeat in a column of their
   own, which on a narrow table is a fifth of the width spent saying one name, and
   it keeps the rows somebody wants read together from being separated by it.

   Space before a block is what marks it, because every row already carries the
   same divider and a heading with only that around it reads as one more row
   rather than as the start of something. Space rather than a heavier rule: the
   rule would compete with the header's own, and there is no hierarchy here to
   argue about - the blocks are peers.

   The first block needs none; the header's rule is already above it. Give each
   block its own tbody, which is also what stops a browser breaking a heading away
   from its rows when the table is printed.

   Usage:
     <table class="tt-table tt-table--compact tt-table--grouped">
       <thead>…</thead>
       <tbody>
         <tr><td colspan="5">…the heading…</td></tr>
         <tr>…</tr>
       </tbody>
       <tbody>…the next block…</tbody>
     </table>
*/
.tt-table--grouped tbody + tbody > tr:first-child > td {
    padding-block-start: var(--space-s);
}

/* GROUP HEADING TBODY
   For a table that is already one tbody per row group (a crew member and their
   entries), where the blocks above those need a heading tbody of their own.
   Only the heading gets the space and weight, so the groups under it stay tight. */
.tt-table tbody.tt-table-group-heading > tr > td {
    font-weight: var(--font-weight-semibold);
}
.tt-table tbody + tbody.tt-table-group-heading > tr > td {
    padding-block-start: var(--space-m);
}

/* INDENTED ROWS
   For rows nested under a heading row (unions under a country, agreements under a
   union). Padding on the cell rather than margin on its text, so a name that wraps
   stays aligned with its first line. The space tokens are fluid, so the indent
   already narrows on small screens. */
.tt-table td.tt-table-indent-1 {
    padding-inline-start: var(--space-xs);
}
.tt-table td.tt-table-indent-2 {
    padding-inline-start: var(--space-m);
}

/* COLORS */
.tt-table--primary {
    --tt-table-divider-header: 1px solid var(--primary-color);
    --tt-table-divider-footer: 1px solid var(--primary-color);
}
.tt-table--accent {
    --tt-table-divider-header: 1px solid var(--accent-color);
    --tt-table-divider-footer: 1px solid var(--accent-color);
}

/* COMPACT */
.tt-table--compact {
    --tt-table-padding-header: var(--tt-table-padding-compact-header);
    --tt-table-padding-body: var(--tt-table-padding-compact-body);
    --tt-table-padding-footer: var(--tt-table-padding-compact-footer);
}
.tt-table--compact-header {
    --tt-table-padding-header: var(--tt-table-padding-compact-header);
}
.tt-table--compact-body {
    --tt-table-padding-body: var(--tt-table-padding-compact-body);
}
.tt-table--compact-footer {
    --tt-table-padding-footer: var(--tt-table-padding-compact-footer);
}

/* Action column for icon buttons (expand/collapse) */
.tt-table-col-action {
    width: 44px;
}

/* Primary column: absorbs remaining space without expanding to fit content */
.tt-table .tt-table-col-primary {
    width: 100%;
    max-width: 0;
    overflow: hidden;
}

/* Job name row: flex container so icon + title link sit on the same line */
.tt-job-name-row {
    display: flex;
    align-items: baseline;
    gap: 0.5em;
    min-width: 0;
    overflow: hidden;
}

/* Job title line: production name + company name on one row; company name truncates with ellipsis */
.tt-job-title {
    display: flex;
    align-items: baseline;
    gap: 0.35em;
    min-width: 0;
    overflow: hidden;
    flex: 1 1 0;
}
.tt-job-production {
    flex-shrink: 0;
    white-space: nowrap;
}
.tt-job-company {
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Position line: department + job title on one row; job title truncates with ellipsis */
.tt-job-position-row {
    display: flex;
    align-items: baseline;
    gap: 0.35em;
    min-width: 0;
    overflow: hidden;
}
.tt-job-department {
    flex-shrink: 0;
    white-space: nowrap;
}
/* Beats Bootstrap's abbr[title] dotted underline and help cursor */
abbr.tt-job-position-short[title] {
    text-decoration: none;
    cursor: inherit;
}
.tt-job-position {
    flex-shrink: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* RESPONSIVE — drop one step-level on narrow screens, shrink action column and icon buttons */
@media (max-width: 576px) {
    .tt-table {
        --tt-table-padding-header: var(--step--3) var(--step--5);
        --tt-table-padding-body: var(--step--3) var(--step--5);
        --tt-table-padding-compact-header: var(--step--4) var(--step--5);
        --tt-table-padding-compact-body: var(--step--5) var(--step--5);
    }
    .tt-table-col-action {
        width: 28px;
    }
    .tt-table td .tt-btn-icon,
    .tt-table th .tt-btn-icon {
        --btn-icon-size: 1.5rem;
    }
}

/* SUPER COMPACT */
.tt-table--super-compact {
    --tt-table-padding-header: var(--tt-table-padding-super-compact-header);
    --tt-table-padding-body: var(--tt-table-padding-super-compact-body);
    --tt-table-padding-footer: var(--tt-table-padding-super-compact-footer);
    font-size: var(--step--2);
}
.tt-table--super-compact-header {
    --tt-table-padding-header: var(--tt-table-padding-super-compact-header);
}
.tt-table--super-compact-body {
    --tt-table-padding-body: var(--tt-table-padding-super-compact-body);
}
.tt-table--super-compact-footer {
    --tt-table-padding-footer: var(--tt-table-padding-super-compact-footer);
}

/* TEXT ALIGN */
/* Right-align last column */
.tt-table--last-col-right tr:not(.no-last-right) > td:last-child:not(:only-child),
.tt-table--last-col-right thead th:last-child,
.tt-table--last-col-right tfoot tr:not(.no-last-right) > td:last-child:not(:only-child),
.tt-table--last-col-right thead th .tt-text-right,
.tt-table--last-col-right td .tt-text-right {
    text-align: right;
}

/* LAST CHILD */
.tt-table tr:not(.no-last-right) > td:last-child:not(:only-child),
.tt-table thead th:last-child,
.tt-table tfoot tr:not(.no-last-right) > td:last-child:not(:only-child),
.tt-table thead th .tt-text-right,
.tt-table td .tt-text-right {
    text-align: right;
}

/* TEXT TABLES — every column holds prose, so the last one is a sentence rather
   than a figure and must stay left-aligned. Matches the LAST CHILD selectors
   above at the same specificity and later in the file, so it wins without
   needing an !important or a longer selector. */
.tt-table--text tr:not(.no-last-right) > td:last-child:not(:only-child),
.tt-table--text thead th:last-child,
.tt-table--text tfoot tr:not(.no-last-right) > td:last-child:not(:only-child) {
    text-align: left;
}

/* Right-align on the cell element itself */
.tt-table th.tt-text-right,
.tt-table td.tt-text-right {
    text-align: right;
}

.tt-table td div {
    white-space: normal;
}

/* Cells that must never wrap (e.g. formatted currency + hours) */
.tt-table .tt-table-col-nowrap,
.tt-table .tt-table-col-nowrap div {
    white-space: nowrap;
}

/* Secondary columns: never wrap, and hide when the card-body container is too narrow */
.tt-table .tt-table-col-secondary,
.tt-table .tt-table-col-secondary div {
    white-space: nowrap;
}

@container (max-width: 560px) {
    .tt-table .tt-table-col-secondary {
        display: none;
    }
}

/* STACK
   When the card body is too narrow, each row wraps into lines: the first cell (the
   row's name) on top, any other unlabelled cell (an action) beside it, then each
   cell with a data-label below as a "label … value" line.
   Add .tt-table-col-panel to a labelled cell to show it as an info panel item
   instead: label above value, sitting beside the other panel cells. */
@container (max-width: 640px) {
    .tt-table--stack thead {
        display: none;
    }
    .tt-table--stack,
    .tt-table--stack tbody {
        display: block;
    }
    .tt-table--stack tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        column-gap: var(--space-m);
        padding: var(--space-2xs) var(--step--5);
    }
    /* Line break between the name/action line and the labelled cells */
    .tt-table--stack tbody tr::after {
        content: "";
        order: 1;
        flex-basis: 100%;
    }
    .tt-table.tt-table--stack tbody td {
        display: block;
        padding: var(--space-3xs) 0;
    }
    /* The name heads the stacked row, a step up so it holds its own beside the action */
    .tt-table--stack td:first-child {
        flex: 1 1 0;
        min-width: 0;
        font-size: var(--step-0);
    }
    .tt-table.tt-table--stack tbody td[data-label] {
        order: 2;
        flex: 1 0 100%;
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: var(--space-xs);
        text-align: right;
        overflow-wrap: anywhere;
    }
    .tt-table--stack td[data-label]::before {
        content: attr(data-label);
        flex-shrink: 0;
        text-align: left;
        color: var(--text-muted);
    }

    /* Label and value sizes match .tt-info-panel-label and .tt-info-panel-value */
    /* Equal shares so panel cells line up across rows, but never narrower than their value */
    .tt-table.tt-table--stack tbody td.tt-table-col-panel {
        flex: 1 1 0;
        min-width: fit-content;
        display: block;
        text-align: left;
        font-size: var(--step--1);
    }
    .tt-table--stack td.tt-table-col-panel::before {
        display: block;
        font-size: var(--step--2);
        text-transform: uppercase;
        letter-spacing: 0.06em;
        margin-bottom: 0.1rem;
    }
}

/* Icons in dedicated table cells don't need inline-text margins — cell padding handles spacing */
.tt-table td .tt-icon {
    margin: 0;
}

/* Entry date/time display used in hours and payroll tables */
.tt-entry-date {
    font-weight: var(--font-weight-semibold);
    line-height: 1.2;
    margin-bottom: 0.1em;
}
.tt-entry-time {
    white-space: nowrap;
    font-size: var(--step--2);
}
.tt-table td .tt-entry-rate {
    white-space: nowrap;
    font-size: var(--step--2);
}
@media (max-width: 576px) {
    .tt-entry-date {
        font-size: var(--step--2);
    }
}
/* UTILITY */
.tt-table tt.nowrap {
    white-space: normal;
}
/* BORDERS */
.tt-table--bordered {
    border: var(--tt-table-outer-border);
}
/* Vertical cell borders */
.tt-table--bordered th,
.tt-table--bordered td {
    border-right: var(--tt-table-divider-body);
}
/* Remove last column border */
.tt-table--bordered th:last-child,
.tt-table--bordered td:last-child {
    border-right: none;
}

/* No borders at all */
.tt-table--no-borders,
.tt-table--no-borders th,
.tt-table--no-borders tr,
.tt-table--no-borders td {
    --tt-table-divider-header: none;
    --tt-table-divider-body: none;
    --tt-table-divider-footer: none;
}
.tt-table--last-row-no-border tbody tr:last-child {
    --tt-table-divider-body: none;
}

/* HIDDEN ROWS */
.hidden-row {
    display: none;
}
tr:not(.hidden-row) {
    animation: fadeIn 0.15s ease-out;
}

/* COLLAPSIBLE GROUPS - a tbody (group-toggle controller) folded down to its heading row */
.tt-group--collapsed > tr:not(:first-child) {
    display: none;
}
/* The button cycles collapsed (expand) → rows shown (expand all) → details open (contract) */
.tt-group--collapsed :is(.tt-group-expand-all-icon, .tt-group-contract-icon),
tbody:not(.tt-group--collapsed) .tt-group-expand-icon,
tbody:not(.tt-group--collapsed).tt-group--detailed .tt-group-expand-all-icon,
tbody:not(.tt-group--collapsed):not(.tt-group--detailed) .tt-group-contract-icon {
    display: none;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(-2px); }
    to { opacity: 1; transform: translateY(0); }
}


/* CLOCKED DAYS
   A strip of days per person: a one-line name heading spanning the days, then a
   rounded slot per day. Weekends and today are marked on the slots rather than
   as column tints, which the heading rows would only cut into pieces.
   Never scrolls: the clocked-days controller hides the days that don't fit. */
.tt-clocked-days {
    --tt-clocked-days-slot: color-mix(in srgb, var(--text-color) 5%, var(--bg-color));
    --tt-clocked-days-weekend: color-mix(in srgb, var(--danger-color) 10%, var(--bg-color));
    /* Day tile size; columns never get narrower than this. */
    --tt-clocked-days-tile: 1.75rem;
    /* The week arrows' column either side of the days. */
    --tt-clocked-days-step: 2.25rem;
    --tt-clocked-days-avatar: 2.5rem;
    --tt-clocked-days-toggle: 1.5rem;
    /* clip, not hidden: hidden would make this the scroll box the date row sticks to. */
    overflow: clip;
    /* So the table's width never widens the box it has to fit into. */
    container-type: inline-size;
}
/* Clips the earliest days rather than the latest until the controller has fitted them. */
.tt-clocked-days--end {
    display: flex;
    justify-content: flex-end;
}
.tt-clocked-days--end > .tt-clocked-days-table {
    flex: none;
}
/* Opened on this week there's no clear button, so the input ends the group. */
[data-clocked-days-end-aligned-value="true"] .tt-clocked-days-from > input:not([type="hidden"]) {
    border-top-right-radius: var(--input-border-radius);
    border-bottom-right-radius: var(--input-border-radius);
}
/* Fixed layout so every day column is exactly as wide as the next: the strip fills
   the box, or overflows at one tile per day when that would squeeze them.
   --tt-clocked-days-count is the number of days shown, set by the controller. */
.tt-clocked-days-table {
    width: max(100%, var(--tt-clocked-days-count) * var(--tt-clocked-days-tile) + 2 * var(--tt-clocked-days-step));
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: 0;
}
.tt-clocked-days-table thead th {
    border-bottom: none;
}
.tt-clocked-days-table tbody tr {
    border-bottom: none;
}

/* Months and dates stick together under the top bar, so they stay in view down a long crew list. */
.tt-clocked-days-table thead {
    position: sticky;
    top: var(--tt-topbar-height);
    z-index: 1;
    background-color: var(--bg-color);
}
/* A month's name over its days; the controller drops it when they have no room for it. */
.tt-clocked-days-table thead th.tt-clocked-days-month {
    padding: var(--space-3xs) 1px 0;
    font-size: var(--step--2);
    font-weight: var(--font-weight-medium);
    text-align: start;
    white-space: nowrap;
}
/* Day header: weekday letter over the date, today outlined as its tiles are. */
/* th.… to match .tt-table thead th:last-child, which would right-align the last day. */
.tt-clocked-days-table thead th.tt-clocked-days-day {
    padding: var(--space-3xs) 1px;
    text-align: center;
    line-height: 1.2;
}
/* A week arrow fills its cell, and so the date row's height. */
.tt-clocked-days-table thead th.tt-clocked-days-step {
    position: relative;
    width: var(--tt-clocked-days-step);
    padding: 0;
}
.tt-clocked-days-step .tt-btn-icon {
    position: absolute;
    /* The space the date cells keep around their heads, so it stands as tall as the today outline. */
    inset-block: var(--space-3xs);
    /* Flush with the table's edge, in line with the avatars and chevrons; spaced only from the days. */
    inset-inline: 0 var(--space-3xs);
    width: auto;
    height: auto;
}
.tt-clocked-days-step:last-child .tt-btn-icon {
    inset-inline: var(--space-3xs) 0;
}
/* Spaced from the days as the next week arrow is, so the chevrons centre on it. */
.tt-clocked-days-table .tt-clocked-days-gutter {
    padding: 0 0 0 var(--space-3xs);
}
/* Opens or folds a job, and all of them from the header. A block with auto margins,
   as the table's last-column rule right-aligns the text in this cell. */
.tt-clocked-days-table .tt-clocked-days-toggle {
    --btn-icon-size: var(--tt-clocked-days-toggle);
    display: flex;
    margin-inline: auto;
    font-size: var(--button-font-size-sm);
}
/* Centred on the job, the name heading's last line, whether or not the person's name is above it.
   That line is half the avatar's height, or its own line height when taller. */
.tt-clocked-days-table .tt-clocked-days-name + .tt-clocked-days-gutter {
    padding-block-end: calc(var(--space-3xs) + (max(1lh, var(--tt-clocked-days-avatar) / 2) - var(--tt-clocked-days-toggle)) / 2);
    font-size: var(--step--2);
    vertical-align: bottom;
}
/* The first row sets a fixed table's columns. */
.tt-clocked-days-table thead th.tt-clocked-days-gutter {
    width: var(--tt-clocked-days-step);
}
.tt-clocked-days-weekday {
    display: block;
    font-size: var(--step--3);
    font-weight: var(--font-weight-normal);
    text-transform: uppercase;
}
.tt-clocked-days-head {
    display: block;
    padding-block: 0.15em;
    border-radius: var(--input-border-radius);
}
.tt-clocked-days-date {
    display: block;
    font-weight: var(--font-weight-medium);
}
.tt-clocked-days-day--weekend .tt-clocked-days-date {
    color: var(--danger-color);
}
.tt-clocked-days-day--today .tt-clocked-days-head {
    box-shadow: inset 0 0 0 var(--border-thin) var(--primary-color);
}

/* Name heading: one muted line across the days. */
.tt-clocked-days-table .tt-clocked-days-name {
    padding: var(--space-s) 0 var(--space-3xs);
    font-weight: inherit;
    text-align: start;
}
.tt-clocked-days-table tbody:first-of-type .tt-clocked-days-name {
    padding-block-start: var(--space-2xs);
}
/* The same person's next job: no avatar, the name kept for screen readers only,
   the job tucked up under the row above. */
.tt-clocked-days-table .tt-clocked-days-repeat .tt-clocked-days-name {
    padding-block-start: var(--space-3xs);
}
.tt-clocked-days-repeat .tt-clocked-days-avatar {
    display: none;
}
.tt-clocked-days-repeat :is(.tt-clocked-days-person, .tt-clocked-days-number) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
/* The avatar down the side of two lines: name and number, then the job. The
   avatar's column is sized outright, so a person's next job, with no avatar,
   still lines up with the one above. The last column takes the slack, so a
   long job title doesn't push the number out. */
.tt-clocked-days-who {
    display: grid;
    grid-template-columns: var(--tt-clocked-days-avatar) auto auto 1fr;
    align-items: center;
    column-gap: var(--space-2xs);
    max-width: min(40rem, 100%);
    font-size: var(--step--2);
}
.tt-clocked-days-avatar {
    grid-row: 1 / span 2;
    width: var(--tt-clocked-days-avatar);
    height: var(--tt-clocked-days-avatar);
    border-radius: var(--input-border-radius);
    object-fit: cover;
}
.tt-clocked-days-person {
    grid-row: 1;
    color: var(--heading-color);
    font-weight: var(--font-weight-semibold);
}
.tt-clocked-days-number {
    grid-row: 1;
    font-variant-numeric: tabular-nums;
}
/* A block of its own, so fit-label measures it and swaps in the short job title. */
.tt-clocked-days-position {
    grid-row: 2;
    grid-column: 2 / -1;
    min-width: 0;
}

/* Day slots: cells pad apart into evenly spaced rounded tiles. */
.tt-clocked-days-table .tt-clocked-days-day {
    padding: 0 1px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.tt-clocked-days-slot {
    display: flex;
    align-items: center;
    justify-content: center;
    height: var(--tt-clocked-days-tile);
    border-radius: var(--input-border-radius);
    background-color: var(--tt-clocked-days-slot);
}
.tt-clocked-days-day--weekend .tt-clocked-days-slot {
    background-color: var(--tt-clocked-days-weekend);
}
.tt-clocked-days-day--today .tt-clocked-days-slot {
    box-shadow: inset 0 0 0 var(--border-thin) var(--primary-color);
}
.tt-clocked-days-mark {
    display: inline-block;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 50%;
    /* Coloured by the entry's status icon class (IconEnum::getClass()), which is a
       text colour - so currentColor, and the dot matches the icon exactly. With no
       class it takes the cell's text colour, as those icons do. */
    background-color: currentColor;
    vertical-align: middle;
}
/* Several entries on a day: two outlined rings overlapping like linked rings,
   each in its own entry's status colour. */
.tt-clocked-days-rings {
    display: inline-flex;
    vertical-align: middle;
}
.tt-clocked-days-mark--ring {
    background-color: transparent;
    border: 2px solid currentColor;
}
.tt-clocked-days-mark--ring + .tt-clocked-days-mark--ring {
    margin-inline-start: -0.3rem;
}
.tt-clocked-days-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3xs) var(--space-s);
    margin: 0 0 var(--space-xs);
    padding: 0;
    list-style: none;
    color: var(--text-color);
    font-size: var(--step--2);
}
.tt-clocked-days-legend li {
    display: flex;
    align-items: center;
    gap: var(--space-3xs);
}
