/*
    Styling for the ProductAuthorshipTableGrid component's header cells, which the
    ProductAuthorshipTableGridHeaderCell component renders: the sort button and its label, the sort
    arrow, header controls and sublines, the bars where a dragged column would land, slanted headers
    and the headers' tooltips.

    These rules read custom properties that SortableTable.css sets on the table's frame and on the
    table, since the header cells share them with the rest of the table:
    - padding: --sortable-table-cell-horizontal-padding-total,
      --sortable-table-header-vertical-padding, --sortable-table-header-trailing-padding;
    - the sort arrow: --sortable-table-sort-arrow-width, --sortable-table-sort-arrow-height,
      --sortable-table-sort-arrow-gap, --sortable-table-sort-arrow-space;
    - the header control: --sortable-table-header-control-height,
      --sortable-table-header-control-inset;
    - lines: --sortable-table-row-line-width, --sortable-table-drop-bar-width,
      --sortable-table-slanted-column-line-width, --sortable-table-frozen-columns-line-color;
    - stacking: --sortable-table-slanted-cell-z-index, --sortable-table-header-part-z-index,
      --sortable-table-open-list-part-z-index, --sortable-table-frozen-header-z-index,
      --sortable-table-edge-control-holder-z-index, --sortable-table-open-list-control-z-index,
      --sortable-table-open-list-header-z-index;
    - slanted headers: --sortable-table-slanted-header-icon-gap,
      --sortable-table-slanted-header-icon-band-height, --sortable-table-slanted-header-height,
      --sortable-table-slanted-header-content-height, --sortable-table-slanted-label-start-height,
      --sortable-table-slanted-label-edge-gap, --sortable-table-slanted-label-room (set from the
      script), --sortable-table-slanted-sort-arrow-right-inset.

    A page can set --sortable-table-slanted-header-line-color, the lines between slanted header
    cells, on an element around the table; it falls back to the table's own line color while unset.
    A header control in a slanted header can read
    --sortable-table-slanted-header-icons-from-right-edge, where the header's icons sit.
*/

/* Where a slanted header's icons sit, from its right edge (set below). Registering it as a length
   makes the browser work it out on the header, in the header's font and line height, and pass the
   result down; an unregistered custom property would be worked out again in the header control,
   whose line height is zero. */
@property --sortable-table-slanted-header-icons-from-right-edge
{
    syntax: "<length>";
    inherits: true;
    initial-value: 0px;
}

.table.sortable-table
{
    /* The sort arrow, the site's thin down arrow icon in a slot one line tall, centered on the line.
       Besides the header cells, a cell's own content can show it beside text that orders something,
       such as a summary row's name: it points down, as for a descending sort, or up with the
       sortable-table-sort-arrow-ascending class, and keeps its room while hidden with the
       sortable-table-sort-arrow-hidden class. */
    .sortable-table-sort-arrow
    {
        display: flex;
        align-items: center;
        justify-content: center;
        width: var(--sortable-table-sort-arrow-width);
        height: 1lh;
        /* Upright is set as scaleY(1), the same function as the flipped arrow's scaleY(-1), so a
           change of direction animates as a vertical flip rather than a turn. */
        transform: scaleY(1);
        transition: transform 0.3s ease;

        /* The icon's arrow fills about 0.7 of its box's height, so the box is the arrow's height
           over 0.7. The arrow is a little wider than the slot and reaches past it on both sides:
           into the gap beside the label, and into the padding after it, or the slanted header's
           right inset. The slot keeps its width, so the columns keep theirs. */
        ion-icon
        {
            flex-shrink: 0;
            font-size: calc(var(--sortable-table-sort-arrow-height) / 0.7);
        }
    }
    td .sortable-table-sort-arrow
    {
        display: inline-flex;
        vertical-align: top;
        margin-left: var(--sortable-table-sort-arrow-gap);

        &.sortable-table-sort-arrow-ascending
        {
            /* Flipped upside down to point up. */
            transform: scaleY(-1);
        }
        &.sortable-table-sort-arrow-hidden
        {
            visibility: hidden;
        }
    }

    /* Styling for the header cells. */
    thead th
    {
        /* Only the sorted header's label is bold, so the headers start out at normal weight. */
        font-weight: normal;
        /* A click anywhere in a header sorts by its column. */
        cursor: pointer;
        /* A line under the header row separates it from the rows below. */
        border-bottom: var(--sortable-table-row-line-width) solid var(--SUBTLE-CELL-SEPARATION-BORDER-COLOR);
        /* A header's content sits at the bottom of the header row, so the labels line up whether or
           not a header keeps a band above its label for a header control. */
        vertical-align: bottom;
        padding-top: var(--sortable-table-header-vertical-padding);
        padding-bottom: var(--sortable-table-header-vertical-padding);
        /* The sort arrow's room is part of the header's content box, so it comes out of the
           trailing padding and the column stays as wide as its cells. */
        padding-right: var(--sortable-table-header-trailing-padding);

        /* A header with a header control keeps a band above its label free for the control, which
           sits in the header's top-right corner, so a label never runs under it. */
        &.sortable-table-header-with-control .sortable-table-header-content
        {
            /* The band reaches from the header's top edge to the control's bottom edge: the
               control's inset plus its height. The header's top padding already covers part of
               that, so it is taken off. */
            padding-top: calc(var(--sortable-table-header-control-inset) + var(--sortable-table-header-control-height) - var(--sortable-table-header-vertical-padding));
        }

        /* Styling for the button that sorts by the column. */
        .sortable-table-sort-button
        {
            /* The button fills the header and looks like plain text. */
            width: 100%;
            padding: 0;
            border: none;
            background: none;
            color: inherit;
            font: inherit;
            text-align: inherit;
            cursor: pointer;
            /* The label and its hidden bold copy share the first grid cell, so the button is sized
               for the bold label whether or not the column is sorted. The label's cell grows up to
               the room beside the sort arrow's cell, so the arrow sits just after a short label. */
            display: grid;
            grid-template-columns: minmax(0, max-content) var(--sortable-table-sort-arrow-space);
            align-items: end;

            &:focus-visible
            {
                outline: 2px solid var(--primary-higher-emphasis-color);
                outline-offset: 1px;
            }
        }
        /* A hovered header's label turns the primary color, as text buttons do, so the header reads
           as clickable; not while the pointer is on one of its controls, which a click doesn't sort. */
        &:hover:not(:has(.sortable-table-header-control:hover, .sortable-table-header-edge-control:hover, .sortable-table-header-subline button:hover)) .sortable-table-sort-button
        {
            color: var(--primary-higher-emphasis-color);
        }

        /* A pressed header brightens while pressed, as the site's buttons do, unless the press is on
           one of its controls, which brighten on their own. */
        &:active:not(:has(.sortable-table-header-control:active, .sortable-table-header-edge-control:active, .sortable-table-header-subline button:active))
        {
            background: var(--neutral-high-emphasis-surface-color);

            .sortable-table-sort-button
            {
                filter: brightness(130%);
            }
        }

        /* A centered header's label sits between two slots, each the sort arrow's room, the arrow in
           the one after it, so the label is centered over the cells' content. The slots come out of
           the header's even padding, so the column stays as wide as its cells. */
        &.sortable-table-center-aligned-cell
        {
            padding-left: calc(var(--sortable-table-cell-horizontal-padding-total) / 2 - var(--sortable-table-sort-arrow-space));
            padding-right: calc(var(--sortable-table-cell-horizontal-padding-total) / 2 - var(--sortable-table-sort-arrow-space));

            .sortable-table-sort-button
            {
                grid-template-columns: var(--sortable-table-sort-arrow-space) minmax(0, max-content) var(--sortable-table-sort-arrow-space);
                justify-content: center;
            }
            .sortable-table-header-label,
            .sortable-table-header-label-bold-space
            {
                grid-area: 1 / 2;
            }
            .sortable-table-sort-arrow
            {
                grid-area: 1 / 3;
            }
        }
        &.sortable-table-right-aligned-cell .sortable-table-sort-button
        {
            justify-content: end;
        }

        /* A label stays on one line, which keeps the header row short; a label too long for the
           column is cut short with an ellipsis, and the whole label then shows in a tooltip. */
        .sortable-table-header-label,
        .sortable-table-header-label-bold-space
        {
            grid-area: 1 / 1;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }
        .sortable-table-header-label-bold-space
        {
            font-weight: bold;
            visibility: hidden;
        }

        &.active .sortable-table-header-label
        {
            font-weight: bold;
        }

        /* A header's sort arrow sits in a one-line slot beside the label, so it is centered on the
           label's line, and shows only while the column is sorted. */
        .sortable-table-sort-arrow
        {
            grid-area: 1 / 2;
            justify-self: end;
            visibility: hidden;
        }
        &.active .sortable-table-sort-arrow
        {
            visibility: visible;
        }
        &.active.ascending .sortable-table-sort-arrow
        {
            /* Flipped upside down to point up. */
            transform: scaleY(-1);
        }

        /* Table.css draws its own arrow at the sorted header's right edge; this table's arrow
           replaces it. */
        &.active.ascending::after,
        &.active.descending::after
        {
            content: none;
        }

        /* The header control, in the header's top-right corner. */
        .sortable-table-header-control
        {
            position: absolute;
            top: var(--sortable-table-header-control-inset);
            right: var(--sortable-table-header-control-inset);
            /* A line of text or an inline icon in the control is as tall as the band kept for it. */
            line-height: var(--sortable-table-header-control-height);
        }

        /* The header's subline, in small low-emphasis text at its bottom right, level with the label. */
        .sortable-table-header-subline
        {
            position: absolute;
            right: var(--sortable-table-header-trailing-padding);
            bottom: var(--sortable-table-header-vertical-padding);
            color: var(--neutral-surface-low-emphasis-contrast-color);
            font-size: 0.8em;
            /* The label's line height, so the subline's text sits on about the label's baseline. */
            line-height: normal;
            white-space: nowrap;
        }

        /* The header holding the control on the line under the header row, while no summary rows
           are under it, sits over the headers beside it and the rows below. */
        &.sortable-table-header-with-edge-control
        {
            z-index: var(--sortable-table-edge-control-holder-z-index);
        }
        &.sortable-table-header-with-edge-control:not(.sortable-table-frozen-cell)
        {
            position: relative;
        }

        /* Styling for the header of a column the user can drag to a new place. The grab cursor
           shows outside the sort button, which keeps the pointer cursor of something to click. */
        &.sortable-table-movable-column
        {
            cursor: grab;
        }

        /* A bar on the side of the header where a dragged column would land, drawn as an inner
           shadow: its horizontal offset is the bar's width, its vertical offset and blur are 0, and
           its color is the highest-emphasis text color. */
        &.sortable-table-drop-before-column
        {
            box-shadow: inset var(--sortable-table-drop-bar-width) 0 0 var(--neutral-surface-highest-emphasis-contrast-color);
        }
        &.sortable-table-drop-after-column
        {
            /* A negative horizontal offset puts the bar on the header's right side. */
            box-shadow: inset calc(-1 * var(--sortable-table-drop-bar-width)) 0 0 var(--neutral-surface-highest-emphasis-contrast-color);
        }
    }
}

/* The headers of a table with slanted headers, whose cells lean 45 degrees to the right. */
.table.sortable-table.sortable-table-with-slanted-headers
{
    /* The frozen headers stay above the slanted cells, which pass under them as columns scroll. */
    thead th.sortable-table-frozen-cell
    {
        z-index: var(--sortable-table-frozen-header-z-index);
    }

    /* The header holding the control on the line under the header row stays above the other frozen
       headers, so the control shows whole where it overlaps them. */
    thead th.sortable-table-frozen-cell.sortable-table-header-with-edge-control
    {
        z-index: var(--sortable-table-edge-control-holder-z-index);
    }

    /* A level header's control sits just above its label at the bottom of the tall header row,
       rather than in the header's top corner, far from the label. */
    thead th:not(.sortable-table-slanted-header) .sortable-table-header-control
    {
        top: auto;
        /* Above the header's bottom padding and the label's line, with a small gap, a visual choice
           that can be tuned. */
        bottom: calc(var(--sortable-table-header-vertical-padding) + 1lh + 0.25rem);
    }

    /* Styling for a header whose cell and label are slanted. Its parts are placed against the
       header, and stacked above the headers to its right, so the parts reaching over them show. */
    thead th.sortable-table-slanted-header
    {
        position: relative;

        /* A frozen slanted header stays in place as the columns scroll; sticky positioning also
           places its slanted parts, as relative positioning does for the others. */
        &.sortable-table-frozen-cell
        {
            position: sticky;
        }
        /* Where the icons' right side sits, as a right offset from the header's right edge: the
           slanted cell's right edge, at the bottom of the icons' band. The cell's top-right corner
           is the header's height right of the header's top-right corner, and its right edge leans
           back left by the band's height at the band's bottom. */
        --sortable-table-slanted-header-icons-from-right-edge: calc(
            var(--sortable-table-slanted-header-icon-band-height) - var(--sortable-table-slanted-header-height));

        /* The header is as tall as its slanted content rises. A change of height, as when the
           longest shown label changes, happens at once: the slanted cells and their icons are placed
           from the final height, so an eased height would leave them out of step mid-change. */
        .sortable-table-header-content
        {
            height: var(--sortable-table-slanted-header-content-height);
        }
        &.sortable-table-header-with-control .sortable-table-header-content
        {
            padding-top: 0;
        }

        /* The slanted cell: the header's box leaning right from its bottom edge, with a line along
           its right side. It brightens while the header is hovered, showing the area a click sorts,
           but not while the pointer is on the control on the line under the header row, which
           belongs to the rows below rather than to the header. */
        .sortable-table-slanted-header-slant
        {
            position: absolute;
            inset: 0;
            z-index: var(--sortable-table-slanted-cell-z-index);
            transform-origin: bottom left;
            transform: skewX(-45deg);
            border-right: var(--sortable-table-slanted-column-line-width) solid var(--sortable-table-slanted-header-line-color, var(--SUBTLE-CELL-SEPARATION-BORDER-COLOR));
        }
        &:hover:not(:has(.sortable-table-header-edge-control:hover)) .sortable-table-slanted-header-slant
        {
            background: var(--neutral-high-emphasis-surface-color);
        }

        /* The upright sort arrow turns the primary color with the label while the header is hovered,
           other than on one of its controls. */
        &:hover:not(:has(.sortable-table-header-control:hover, .sortable-table-header-edge-control:hover, .sortable-table-header-subline button:hover)) .sortable-table-slanted-sort-arrow
        {
            color: var(--primary-higher-emphasis-color);
        }

        /* The last frozen header's line to the scrolled columns runs along its slanted cell's right
           edge rather than up its upright edge, which keeps its width so the columns stay in place. */
        &.sortable-table-last-frozen-cell
        {
            border-right-color: transparent;

            .sortable-table-slanted-header-slant
            {
                border-right-color: var(--sortable-table-frozen-columns-line-color, var(--SUBTLE-CELL-SEPARATION-BORDER-COLOR));
            }
        }

        /* A pressed slanted header brightens across its whole slanted cell, and only there: the
           header's own box keeps its background, so the slanted cell's edges stay sharp. */
        &:active:not(:has(.sortable-table-header-control:active, .sortable-table-header-edge-control:active, .sortable-table-header-subline button:active))
        {
            background: var(--neutral-medium-emphasis-surface-color);

            .sortable-table-slanted-header-slant
            {
                background: var(--neutral-higher-emphasis-surface-color);
            }
        }

        /* Where a dragged column would land shows as a bar along the slanted cell's edge on that
           side, slanted with the cell, rather than along the header's upright edge. */
        &.sortable-table-drop-before-column,
        &.sortable-table-drop-after-column
        {
            box-shadow: none;
        }
        &.sortable-table-drop-before-column .sortable-table-slanted-header-slant
        {
            /* As on an upright header: an inner shadow whose horizontal offset is the bar's width,
               with no vertical offset or blur. */
            box-shadow: inset var(--sortable-table-drop-bar-width) 0 0 var(--neutral-surface-highest-emphasis-contrast-color);
        }
        &.sortable-table-drop-after-column .sortable-table-slanted-header-slant
        {
            /* A negative horizontal offset puts the bar on the slanted cell's right side. */
            box-shadow: inset calc(-1 * var(--sortable-table-drop-bar-width)) 0 0 var(--neutral-surface-highest-emphasis-contrast-color);
        }

        /* The label turns about its bottom-left corner. It starts where its line, turned, keeps the
           edge gap from the cell's slanted left edge: the edge gap and the line, over the sine of 45
           degrees, to the right of where that edge meets the label's starting height. */
        .sortable-table-header-content > *
        {
            position: absolute;
            left: calc(
                (var(--sortable-table-slanted-label-edge-gap) + 1lh) * 1.4142 +
                var(--sortable-table-slanted-label-start-height));
            bottom: var(--sortable-table-slanted-label-start-height);
            z-index: var(--sortable-table-header-part-z-index);
            transform-origin: bottom left;
            transform: rotate(-45deg);
        }

        /* The button is as wide as its label, up to the label's room, and holds no arrow. */
        .sortable-table-sort-button
        {
            width: max-content;
            max-width: var(--sortable-table-slanted-label-room);
            grid-template-columns: minmax(0, max-content);
        }

        /* The subline is a second, smaller slanted line beside the label, on the side away from the
           cell's left edge. It starts above the upright sort arrow, so the two never meet, and keeps
           this gap from the label's line. The label's line is taken as 1.5 of the subline's ems, since
           the subline's font is 0.8 of the label's and a line of text is about 1.2 of its font. */
        --sortable-table-slanted-subline-gap: 0.15rem;
        .sortable-table-header-subline
        {
            /* The subline starts at the header's bottom padding, where the upright sort arrow's
               bottom sits, plus the arrow's one-line height. */
            --sortable-table-slanted-subline-start-height: calc(var(--sortable-table-header-vertical-padding) + 1.5em);
            right: auto;
            /* Placed as the label is: the edge gap, the label's line, the gap from it, and the
               subline's own line, over the sine of 45 degrees, to the right of where the cell's left
               edge meets the subline's starting height. */
            left: calc(
                (var(--sortable-table-slanted-label-edge-gap) + 1.5em + var(--sortable-table-slanted-subline-gap) + 1lh) * 1.4142 +
                var(--sortable-table-slanted-subline-start-height));
            bottom: var(--sortable-table-slanted-subline-start-height);
            z-index: var(--sortable-table-header-part-z-index);
            max-width: var(--sortable-table-slanted-label-room);
            overflow: hidden;
            text-overflow: ellipsis;
            transform-origin: bottom left;
            transform: rotate(-45deg);
        }

        /* A subline that follows the label continues the label's line, a small gap after it, in
           the label's size and color, and shows whole, so a dropdown list in it can reach past the
           header. The gap is a visual choice and can be tuned. */
        .sortable-table-header-label-line
        {
            display: flex;
            align-items: end;
            gap: 1ch;

            .sortable-table-header-subline
            {
                position: static;
                max-width: none;
                overflow: visible;
                color: inherit;
                font-size: 1em;
                transform: none;
            }
        }

        /* While a dropdown list is open in a header's subline, the header sits above every other
           part of the table's head, the control on the line under the header row and the summary
           rows included, and the subline above the header's other parts, so nothing draws over the
           list. While one is open in a header control, only the control is raised, above the
           headers to its right, whose slanted labels would otherwise cover the list; raising the
           header would let its slanted cell cover the labels beside it. */
        &:has(.sortable-table-header-subline [role='listbox'])
        {
            z-index: var(--sortable-table-open-list-header-z-index);
        }
        .sortable-table-header-subline:has([role='listbox']),
        .sortable-table-header-content > :has(.sortable-table-header-subline [role='listbox'])
        {
            z-index: var(--sortable-table-open-list-part-z-index);
        }
        .sortable-table-header-control:has([role='listbox'])
        {
            z-index: var(--sortable-table-open-list-control-z-index);
        }

        /* The sort arrow stands upright in the header's bottom-right corner. */
        .sortable-table-slanted-sort-arrow
        {
            position: absolute;
            right: var(--sortable-table-slanted-sort-arrow-right-inset);
            bottom: var(--sortable-table-header-vertical-padding);
            z-index: var(--sortable-table-header-part-z-index);
        }

        /* The header control sits at the top of the slanted cell, against its right edge. */
        .sortable-table-header-control
        {
            top: var(--sortable-table-slanted-header-icon-gap);
            /* The icons' right side, kept the icon gap in from the slanted cell's right edge. */
            right: calc(var(--sortable-table-slanted-header-icons-from-right-edge) + var(--sortable-table-slanted-header-icon-gap));
            z-index: var(--sortable-table-header-part-z-index);
            line-height: 0;
        }
    }
}

/* A header's tooltip leaves out its label's line while the label was last measured as fitting,
   keeping the lines about sorting and dragging. */
.tooltip.sortable-table-untruncated-label-tooltip .sortable-table-label-tooltip-label
{
    display: none;
}

/* A movable column's header tooltip, which covers the whole header other than its controls, fades
   in as tooltips do but is hidden at once, rather than fading out, when the pointer leaves the
   label, so it never lingers over a header control as the pointer moves to it. */
.tooltip.sortable-table-movable-label-tooltip:not(.visible)
{
    visibility: hidden;
}

/* The hints about sorting and dragging, when they share a line under the label's whole text or a
   tooltip line: a little apart from the text above them and in medium-emphasis gray text, so they
   don't read as part of it. */
.tooltip .sortable-table-label-tooltip-actions-on-one-line
{
    margin-top: 0.3em;
    color: var(--neutral-surface-medium-emphasis-contrast-color);
}
