/**
 * Data display: tables, stats, meta chips, progress, steppers, toolbars
 *
 * These are the parts every organiser screen shares. They lived in each page's
 * own stylesheet before, which is why the same participants table was a
 * different colour on manage event than on preview and send.
 */

/* ============================================
   TABLE
   ============================================ */

/*
 * Bootstrap paints every cell itself — `.table > :not(caption) > * > *` lays an
 * inset shadow the full size of the cell in --bs-table-bg. That shadow sits in
 * front of the row's own background, so a tinted row (row-pending) was invisible
 * and the cream card face was covered by white. Both variables are cleared here
 * so the card shows through and a row tint is the thing you see.
 */
.data-table,
.admin-table,
.card table,
table.table {
    --bs-table-bg: transparent;
    --bs-table-accent-bg: transparent;

    width: 100%;
    border-collapse: collapse;
    color: var(--text-on-light);
    font-size: var(--font-size-base);
}

.card table > :not(caption) > * > *,
table.table > :not(caption) > * > * {
    background-color: transparent;
    box-shadow: none;
}

.data-table th,
.admin-table th,
.card table th,
table.table th {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-on-light-hairline);
    color: var(--text-on-light-muted);
    font-family: var(--font-body);
    font-size: 0.71875rem;   /* 11.5px */
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-eyebrow);
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
}

.data-table td,
.admin-table td,
.card table td,
table.table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-on-light-hairline);
    vertical-align: middle;
    overflow-wrap: anywhere;
}

.data-table tbody tr:last-child td,
.admin-table tbody tr:last-child td,
.card table tbody tr:last-child td {
    border-bottom: none;
}

.data-table tbody tr,
.admin-table tbody tr,
.card table tbody tr {
    transition: background-color var(--duration-fast) var(--easing);
}

.data-table tbody tr:hover,
.admin-table tbody tr:hover,
.card table tbody tr:hover {
    background: rgba(26, 77, 77, 0.035);
}

/* A row that needs the organiser to do something carries a tint, and the row
   also carries the action — the tint alone is not the message. */
.data-table tr.needs-action,
tr.row-pending {
    background: rgba(230, 72, 46, 0.045);
}

.data-table tr.needs-action:hover,
tr.row-pending:hover {
    background: rgba(230, 72, 46, 0.075);
}

.table-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/*
 * A pill says one word and does not break it. It used to be allowed to wrap so
 * a timestamp could sit inside it; the timestamp is its own line now, and the
 * cell's overflow-wrap: anywhere was breaking "Confirmed" mid-glyph.
 */
.data-table .badge,
.admin-table .badge,
.card table .badge {
    white-space: nowrap;
    overflow-wrap: normal;
}

/* A wide table scrolls inside its own box rather than pushing the page
   sideways. Bootstrap supplies .table-responsive, but the identity must not
   depend on a CDN being reachable. */
.table-scroll,
.table-responsive {
    width: 100%;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
}

/*
 * Below the tablet width a row-per-record table becomes a stack of labelled
 * rows. Only tables that opt in stack: a matrix like the exclusions grid is a
 * grid in both directions and has to keep its shape and scroll instead.
 *
 * The boundary is 799 rather than 768 because 769-799 is the one band where
 * the participants table neither stacks nor fits: the shell is 689-719px there
 * and the table's min-content is 706px, so the row-actions column fell off the
 * clipped edge. Stacking one notch higher removes the band entirely.
 */
@media (max-width: 799px) {
    .table-stack thead,
    .participant-table-shell table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
    }

    .table-stack tr,
    .participant-table-shell table tr {
        display: block;
        padding: var(--space-3) 0;
        border-bottom: 1px solid var(--border-on-light-hairline);
    }

    /*
     * Label column, value column. Nothing else.
     *
     * These cells were `display: flex; justify-content: space-between`, which
     * only behaves when a cell holds exactly one child besides its label. It
     * does not: Confirmed holds a badge *and* a date, so space-between pushed
     * the badge into the middle of the row, and Person's avatar block was wide
     * enough to be thrown against the right edge. One participant's five
     * values landed on four different alignments.
     *
     * A two-column grid says the thing directly — the label is always column
     * one, every value is always column two — so a cell with two children
     * stacks them down the value column instead of distributing them across
     * the row. Every value in the stack now starts at the same x, whatever the
     * cell happens to contain.
     */
    .table-stack td,
    .participant-table-shell table td {
        display: grid;
        grid-template-columns: minmax(6rem, 30%) minmax(0, 1fr);
        align-items: baseline;
        /* Grid items stretch by default, which turned every status pill into a
           full-width bar. A badge should hug the word it carries. */
        justify-items: start;
        column-gap: var(--space-4);
        row-gap: var(--space-1);
        padding: var(--space-1) var(--space-4);
        border: none;
        overflow-wrap: anywhere;
    }

    .table-stack td::before,
    .participant-table-shell table td::before {
        content: attr(data-label);
        grid-column: 1;
        grid-row: 1;
        color: var(--text-on-light-muted);
        font-size: 0.71875rem;
        font-weight: var(--font-weight-semibold);
        letter-spacing: var(--tracking-eyebrow);
        text-transform: uppercase;
    }

    /* Every real child belongs to the value column, however many there are. */
    .table-stack td > *,
    .participant-table-shell table td > * {
        grid-column: 2;
        min-width: 0;
    }

    /*
     * The actions cell is 44px wide and right-aligned as a table column, which
     * are both meaningless once it is a labelled row — and they kept its value
     * column 110px left of every sibling's, so "Actions" was the one line in
     * the stack that did not line up.
     */
    .participant-table-shell table td.row-menu-cell {
        width: auto;
        text-align: left;
    }

    .table-stack td:empty,
    .participant-table-shell table td:empty {
        display: none;
    }

    .table-stack .badge,
    .participant-table-shell table .badge {
        height: auto;
        min-height: 24px;
        white-space: normal;
        text-align: left;
    }
}

/* ============================================
   STAT

   A number on the card face with a hairline between it and the next. The
   previous build sank each one into an inset well.
   ============================================ */

.stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0;
}

.stat-card,
.stat-compact {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4) var(--space-5);
    border-right: 1px solid var(--border-on-light-hairline);
    background: transparent;
    box-shadow: none;
    color: var(--text-on-light);
}

.stat-row > :last-child {
    border-right: none;
}

.stat-card-value,
.stat-compact-value {
    font-family: var(--font-display);
    font-size: 2.25rem;   /* 36px */
    font-weight: var(--font-weight-normal);
    letter-spacing: var(--tracking-display);
    line-height: 1;
    color: var(--text-on-light);
}

.stat-card-label,
.stat-compact-label {
    color: var(--text-on-light-muted);
    font-size: var(--font-size-sm);
}

.stat-card-delta {
    font-size: var(--font-size-sm);
}

.stat-card-delta-up { color: var(--color-success); }
.stat-card-delta-down { color: var(--color-danger); }

.stat-card-icon-img,
.stat-compact-icon {
    width: 26px;
    height: 26px;
    object-fit: contain;
}

@media (max-width: 640px) {
    .stat-card,
    .stat-compact {
        border-right: none;
        border-bottom: 1px solid var(--border-on-light-hairline);
    }
}

/* ============================================
   META CHIP

   Budget, theme, exchange date: a small clay icon, a label and a value.
   ============================================ */

.meta-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.meta-chip,
.event-detail-item {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--surface-border);
    border-radius: var(--radius-full);
    background: var(--surface-hover);
    color: var(--surface-text);
    font-size: var(--font-size-sm);
}



.detail-icon {
    width: 26px;
    height: 26px;
    object-fit: contain;
}

.detail-label {
    color: var(--surface-text-muted);
}



.detail-value {
    font-weight: var(--font-weight-semibold);
}

/* ============================================
   PROGRESS
   ============================================ */

.progress-row {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.progress-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-1);
}

.progress-label-bar {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-on-light-muted);
    font-size: var(--font-size-sm);
}

.progress-percentage {
    color: var(--text-on-light);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
}

.progress-bar-container,
.progress-track {
    height: 5px;
    border-radius: var(--radius-full);
    background: rgba(26, 77, 77, 0.12);
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    border-radius: var(--radius-full);
    background: var(--color-gold);
    transition: width var(--duration-slow) var(--easing);
}

.progress-bar-fill.emails { background: var(--color-success-fill); }
.progress-bar-fill.wishlist { background: var(--color-gold); }
.progress-bar-fill.complete { background: var(--color-success-fill); }

.on-dark .progress-bar-container,
.on-dark .progress-track {
    background: rgba(247, 243, 232, 0.16);
}

.on-dark .progress-label-bar { color: var(--text-on-dark-muted); }
.on-dark .progress-percentage { color: var(--color-cream); }

/* ============================================
   STEPPER

   Gold for the run already completed, the accent red for the step in hand,
   45% for steps not yet reachable. The completed connector ends on the centre
   of the current marker, not before it.
   ============================================ */

.stepper {
    display: flex;
    align-items: flex-start;
    gap: 0;
}

.stepper-step {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    text-align: center;
    color: var(--color-cream);
}

/*
 * The connector joins two markers; it does not run through them.
 *
 * It used to span the full cell centre-to-centre at the markers' own vertical
 * centre, and only the marker's background hid it. That works for complete and
 * current steps, whose discs are opaque gold and red — but an upcoming step's
 * disc is 10% opaque with a transparent-background webp on top, so the rule
 * was drawn straight across the envelope and through the Christmas tree's
 * trunk. Insetting it by the marker's radius plus a little air means there is
 * nothing to hide: the rule stops where the disc starts, at every state.
 */
.stepper-step::before {
    content: '';
    position: absolute;
    top: 27px;
    left: calc(-50% + 32px);
    width: calc(100% - 64px);
    height: 2px;
    background: rgba(247, 243, 232, 0.20);
}

.stepper-step:first-child::before {
    display: none;
}

.stepper-step.is-complete::before,
.stepper-step.is-current::before {
    background: var(--color-gold);
}

/*
 * Nothing past the current step gets a gold connector, whatever its own state.
 * See the note in src/views/components/progress-tracker.php: a later step can
 * genuinely be complete, but a gold run reaching past the current marker says
 * the step being waited on is already behind us.
 */
.stepper-step.is-beyond::before {
    background: rgba(247, 243, 232, 0.20);
}

.stepper-marker {
    position: relative;
    z-index: 1;
    display: flex;
    /*
     * A circle only if it cannot be squeezed. Without this the two steps with
     * the longest titles lost the argument in the mobile flex row and their
     * markers measured 41.9x56 and 50.9x56 — and border-radius: 50% renders a
     * squeezed box as an ellipse, so two of the six were visibly ovals at 390.
     */
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-full);
    background: rgba(247, 243, 232, 0.10);
}

.stepper-marker img {
    width: 32px;
    height: 32px;
    object-fit: contain;
}

/*
 * Even out the artwork's aspect ratios.
 *
 * `contain` in a 32x32 box preserves each asset's own proportions, so the
 * rendered size follows whatever the illustrator drew: bear, bell and present
 * are ~0.90 and render 29x32, but the tree is 0.70 and renders 22x32 — 24%
 * narrower than every sibling and visibly the runt of the row — while the
 * letter is 1.24 and renders 32x26.
 *
 * These scales bring both back to the same rendered *area* as the three that
 * agree (sqrt(928/704) and sqrt(928/832)), which is much closer to how the eye
 * compares them than matching one edge would be.
 */
.stepper-mark-christmas_tree { transform: scale(1.15); }
.stepper-mark-letter { transform: scale(1.06); }

.stepper-step.is-complete .stepper-marker {
    background: var(--color-gold);
}

/*
 * The ring is drawn inside the marker, not around it.
 *
 * An outline with a positive offset sits outside the border box and takes no
 * layout space, so at 390 — where the markers form a left-hand column — the
 * current step's ring hung 6px into the page gutter and it alone appeared to
 * break the column. A negative offset draws the same ring within the 56px, in
 * the pale red so it still reads against the disc.
 */
.stepper-step.is-current .stepper-marker {
    background: var(--color-red);
    outline: 3px solid var(--color-red-pale);
    outline-offset: -3px;
}

.stepper-step.is-upcoming {
    opacity: 0.45;
}

.stepper-title {
    font-weight: var(--font-weight-semibold);
}

.stepper-description {
    color: var(--text-on-dark-muted);
    font-size: var(--font-size-sm);
}

@media (max-width: 768px) {
    .stepper {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-4);
    }

    /*
     * Marker in one column, the words stacked in the other.
     *
     * This was flex-direction: row, so the marker, the title and the
     * description were three items in a single row — which means each
     * description started wherever its own title happened to end. Measured at
     * 390: six sibling rows whose descriptions began at 209, 183, 257, 218,
     * 192 and 193, a 74px spread down what should read as one column.
     */
    .stepper-step {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-areas:
            "marker title"
            "marker description";
        align-items: center;
        column-gap: var(--space-4);
        row-gap: 2px;
        text-align: left;
    }

    .stepper-marker { grid-area: marker; }
    .stepper-title { grid-area: title; align-self: end; }
    .stepper-description { grid-area: description; align-self: start; }

    .stepper-step::before {
        display: none;
    }
}

/* ============================================
   TOOLBAR AND SEGMENTED FILTER
   ============================================ */

.toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
}

.segmented {
    display: inline-flex;
    padding: 3px;
    border: 1px solid var(--border-on-dark);
    border-radius: var(--radius-full);
    background: rgba(247, 243, 232, 0.06);
}

.segmented-option {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 32px;
    padding: 0 var(--space-4);
    border: none;
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--text-on-dark-muted);
    font-family: var(--font-body);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--easing),
                color var(--duration-fast) var(--easing);
}

.segmented-option:hover {
    color: var(--color-cream);
}

.segmented-option[aria-pressed='true'],
.segmented-option.is-selected {
    background: var(--color-gold);
    color: var(--color-on-gold);
}

.segmented-count {
    opacity: 0.72;
}

/*
 * The same control inside a cream card. The track and the unselected options
 * have to read against ink rather than cream, so only the two colours change;
 * the geometry is shared.
 */
.segmented-on-light {
    border-color: var(--border-on-light);
    background: rgba(26, 77, 77, 0.06);
}

.segmented-on-light .segmented-option {
    color: var(--text-on-light-muted);
}

.segmented-on-light .segmented-option:hover {
    color: var(--text-on-light);
}

.segmented-on-light .segmented-option[aria-pressed='true'],
.segmented-on-light .segmented-option.is-selected {
    background: var(--color-teal-dark);
    color: var(--text-on-dark);
}

/*
 * A search field with its icon inside it. The icon is decorative — the field
 * carries a real label, visually hidden — so it is positioned rather than
 * placed in the flow, and the input is padded to clear it.
 */
.toolbar-search {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 220px;
    max-width: 320px;
}

.toolbar-search svg {
    position: absolute;
    left: var(--space-4);
    color: var(--surface-text-muted);
    pointer-events: none;
}

.toolbar-search .form-control {
    height: 40px;
    padding-left: calc(var(--space-4) + 18px + var(--space-2));
    border-radius: var(--radius-full);
}

/* Said in words, where the rows would have been. */
.filter-empty {
    margin-bottom: var(--space-6);
    color: var(--surface-text-muted);
    font-size: var(--font-size-md);
}

/* ============================================
   PLACEHOLDER CHIPS

   The email template placeholders, dropped into a field rather than typed.
   ============================================ */

.chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.chip {
    display: inline-flex;
    align-items: center;
    height: 22px;
    padding: 0 var(--space-2);
    border: none;
    border-radius: 6px;
    background: var(--color-warning-tint);
    color: var(--color-gold-ink);
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
}

.chip:hover {
    background: rgba(225, 193, 110, 0.44);
}
