/**
 * Feature layer
 *
 * Parts of the product that are specific enough not to belong in the component
 * layer but are shared by more than one screen: the snow, the journey feedback
 * card, the public wishlist chrome, and the send confirmation dialog.
 *
 * Everything this file used to restate — buttons, alerts, focus rings, the
 * navigation, the responsive participants table — now lives in the component
 * layer. It carried 41 `!important` declarations to win those fights; it
 * carries none.
 */

html {
    scroll-padding-top: 6rem;
}

body {
    overflow-x: hidden;
}

#main-content {
    min-height: calc(100vh - 72px);
}

/* ============================================
   SNOW

   Five flakes, not ten. It is the one piece of ambient motion kept, and it
   stops entirely for readers who have asked for less.
   ============================================ */

.festive-snow {
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 1;
}

.festive-snow span {
    --drift: 72px;
    position: absolute;
    top: -3rem;
    left: var(--snow-left);
    color: rgba(255, 255, 255, 0.5);
    font-size: clamp(0.8rem, 1.5vw, 1.4rem);
    animation: ui-snowfall var(--snow-duration) linear var(--snow-delay) infinite;
}

.festive-snow span:nth-child(1) { --snow-left: 8%; --snow-duration: 15s; --snow-delay: -2s; }
.festive-snow span:nth-child(2) { --snow-left: 27%; --snow-duration: 18s; --snow-delay: -9s; --drift: -60px; }
.festive-snow span:nth-child(3) { --snow-left: 51%; --snow-duration: 14s; --snow-delay: -5s; }
.festive-snow span:nth-child(4) { --snow-left: 73%; --snow-duration: 20s; --snow-delay: -12s; --drift: -80px; }
.festive-snow span:nth-child(5) { --snow-left: 92%; --snow-duration: 17s; --snow-delay: -1s; }

@keyframes ui-snowfall {
    0% { transform: translate3d(0, -8vh, 0) rotate(0); opacity: 0; }
    12% { opacity: 0.72; }
    88% { opacity: 0.72; }
    100% { transform: translate3d(var(--drift), 108vh, 0) rotate(180deg); opacity: 0; }
}

/* ============================================
   PENDING STATE
   ============================================ */

.ui-loading {
    cursor: wait;
    opacity: 0.82;
}

/* ============================================
   EVENT ACCESS STATE
   ============================================ */

.access-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

/*
 * This says what the wishlist's access is. It is not a control.
 *
 * It used to carry a 1px border, a pill radius, a fill and semibold text —
 * every cue a button has — and it sits directly beneath a row of real outline
 * buttons at a near-identical height. So the row read as five buttons followed
 * by two more, and two of them did nothing when clicked. Dropping the border
 * and the weight is what separates a state from an action; the fill stays,
 * quietly, so the pair still reads as a group.
 */
.access-status-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-full);
    background: rgba(247, 243, 232, 0.06);
    color: var(--text-on-dark-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
}

.copy-link-button {
    min-height: 40px;
}

/* ============================================
   PUBLIC WISHLIST

   The most festive surface, because it is what participants see.
   ============================================ */

.wishlist-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-10);
    text-align: center;
}

.wishlist-decoration-scene {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: var(--space-2);
    max-width: 190px;
    margin: 0 auto;
}

.wishlist-decoration-scene img {
    flex: 0 0 auto;
    object-fit: contain;
}

.wish-save-status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-lg);
    /* This sits straight on the teal ground, so the tint needs a cream face
       under it or the green text lands on teal at 1.2:1. */
    background: var(--color-cream);
    color: var(--color-success);
    font-weight: var(--font-weight-semibold);
}

.wishlist-directory {
    position: relative;
    z-index: 3;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-8);
    padding: var(--space-1) 0 var(--space-3);
}

.wishlist-directory a {
    flex: 0 0 auto;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-on-dark);
    border-radius: var(--radius-full);
    background: rgba(247, 243, 232, 0.08);
    color: var(--color-cream);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-decoration: none;
}

.wishlist-directory a:hover,
.wishlist-directory a:focus-visible {
    background: var(--color-gold);
    color: var(--color-on-gold);
}

.wishlist-directory + .row .card {
    scroll-margin-top: 7rem;
}

/* An empty wish says so in words rather than showing nothing. */
.wish-empty {
    color: var(--text-on-light-muted);
    font-style: italic;
}

/* ============================================
   JOURNEY FEEDBACK
   ============================================ */

.journey-feedback {
    position: relative;
    z-index: 3;
    width: min(100%, 680px);
    margin: var(--space-8) auto;
    padding: var(--space-5);
    border: none;
    border-radius: var(--radius-xl);
    background: var(--card-face);
    box-shadow: var(--shadow-card);
    color: var(--text-on-light);
}

.journey-feedback[hidden] {
    display: none;
}

.journey-feedback-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
}

.journey-feedback-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--display-sm);
    font-weight: var(--font-weight-normal);
}

.journey-feedback-subtitle {
    margin: var(--space-1) 0 0;
    color: var(--text-on-light-muted);
    font-size: var(--font-size-base);
}

.journey-feedback-dismiss {
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
    border: 0;
    border-radius: var(--radius-full);
    background: rgba(26, 77, 77, 0.08);
    color: var(--text-on-light);
    font-size: 1.25rem;
}

.feedback-rating {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: var(--space-4) 0;
    padding: 0;
    border: 0;
}

.feedback-rating legend {
    margin-bottom: var(--space-2);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
}

.feedback-rating input {
    position: absolute;
    opacity: 0;
}

.feedback-rating label {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--border-on-light);
    border-radius: var(--radius-full);
    background: var(--color-white);
    color: var(--color-gold-ink);
    cursor: pointer;
    font-size: 1.25rem;
    transition: background-color var(--duration-fast) var(--easing),
                color var(--duration-fast) var(--easing);
}

.feedback-rating label:hover,
.feedback-rating input:checked + label {
    background: var(--color-gold);
    color: var(--color-on-gold);
}

.feedback-rating input:focus-visible + label {
    outline: 2px solid var(--color-gold);
    outline-offset: 3px;
    box-shadow: var(--focus-ring);
}

.feedback-comment {
    min-height: 88px;
    resize: vertical;
}

.feedback-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    margin-top: var(--space-3);
}

.feedback-privacy {
    max-width: 32rem;
    margin: 0;
    color: var(--text-on-light-muted);
    font-size: var(--font-size-xs);
}

.feedback-result {
    margin: var(--space-3) 0 0;
    font-weight: var(--font-weight-semibold);
}

/* ============================================
   FEEDBACK SUMMARY (dashboard)
   ============================================ */

.feedback-summary {
    position: relative;
    z-index: 2;
    margin-top: var(--space-10);
    padding: var(--space-6);
    border: 1px solid var(--border-on-dark);
    border-radius: var(--radius-xl);
    background: rgba(13, 59, 46, 0.42);
    color: var(--color-cream);
}

.feedback-summary-heading {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-6);
}

.feedback-summary-heading h2,
.feedback-summary-heading p {
    margin: 0;
}

.feedback-summary-heading h2 {
    color: var(--color-cream);
    font-size: var(--display-sm);
}

.feedback-summary-heading > p {
    max-width: 34rem;
    color: var(--text-on-dark-muted);
}

.feedback-summary-kicker {
    color: var(--color-gold);
    font-size: 0.71875rem;
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
}

.feedback-summary-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-3);
    margin-top: var(--space-5);
}

.feedback-summary-card {
    display: grid;
    gap: var(--space-1);
    padding: var(--space-4);
    border-radius: var(--radius-card);
    background: rgba(247, 243, 232, 0.08);
}

.feedback-summary-card strong {
    color: var(--color-gold);
    font-family: var(--font-display);
    font-size: var(--display-sm);
    font-weight: var(--font-weight-normal);
}

.feedback-summary-card small {
    color: var(--text-on-dark-muted);
}

/* ============================================
   DASHBOARD GRID
   ============================================ */

.dashboard-events-grid {
    margin-top: var(--space-5);
    --bs-gutter-y: 1.5rem;
}

.dashboard-events-grid > * {
    display: flex;
}

.dashboard-events-grid .event-card {
    width: 100%;
}

@media (min-width: 992px) {
    .dashboard-events-grid > :only-child {
        width: 50%;
    }
}

/* ============================================
   PREVIEW AND SEND
   ============================================ */

.participant-header-button {
    width: 100%;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
}

.receiver-blurred {
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
}

.participant-table-shell {
    width: 100%;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
}

/*
 * Make the scroller admit that it scrolls.
 *
 * This element has been `overflow-x: auto` all along, so nothing was ever
 * truly unreachable — but Chromium (and macOS everywhere) draws an *overlay*
 * scrollbar, which is invisible until you already know to scroll and reserves
 * no space. `offsetWidth - clientWidth` measured 0 at every clipping width,
 * which is exactly what made this silent: the row-actions column, the only
 * route to "wishlist link" and "delete participant", simply was not there.
 *
 * Giving ::-webkit-scrollbar a size opts the element out of overlay scrollbars
 * and back into a classic one that takes layout space and is always visible
 * while the content overflows. This is the affordance that holds at any width
 * and any content length, rather than one more breakpoint to get wrong.
 */
.participant-table-shell::-webkit-scrollbar {
    height: 10px;
}

.participant-table-shell::-webkit-scrollbar-track {
    border-radius: var(--radius-full);
    background: var(--color-border-light);
}

.participant-table-shell::-webkit-scrollbar-thumb {
    border-radius: var(--radius-full);
    background: var(--color-border);
}

/*
 * Let the headers wrap, so the table can actually fit its column.
 *
 * table.table th is nowrap, which makes "HAS MADE A WISH" and "EMAIL STATUS"
 * unshrinkable — so on a populated event the table measured 817px inside a
 * 744px scroller and the fifth column, the row-actions menu, sat 57px past the
 * clipped edge with no scrollbar to say so. That column is the only route to
 * "wishlist link" and "delete participant", so on a real event both had no
 * visible affordance at all. Two-line headers cost a few pixels of height; a
 * hidden delete costs the organiser the feature.
 */
.participant-table-shell table th {
    white-space: normal;
}

/*
 * Align the row's cells to the top, not the middle.
 *
 * The Confirmed cell stacks a badge over a date while its neighbours hold one
 * line, and centring each cell's whole block put the badges 13px apart across a
 * single row — a broken baseline all the way down the table.
 */
.participant-table-shell table td {
    vertical-align: top;
}

/*
 * The participants table has six columns and two of them hold long strings
 * (email addresses and full timestamps). Below the tablet width it stacks; in
 * between it scrolls; at desk width it fits, because the cells wrap.
 *
 * There used to be a `min-width: 760px` here for 769-1100. It was the cause of
 * the clip it was meant to prevent: 760px is *wider* than the table's own
 * min-content (706px once the headers wrap), so it pushed the row-actions
 * column past the shell's edge at every width from 769 to 839, where the shell
 * is only 689-750px. Letting the table find its own min-content is strictly
 * better — it fits in more places, and where it genuinely cannot fit, the
 * scrollbar below says so.
 */

@media (max-width: 799px) {
    .participant-table-shell {
        overflow: visible;
    }

    .participant-table-shell table {
        min-width: 0;
    }
}

.send-confirm-dialog {
    position: fixed;
    inset: 0;
    width: min(calc(100% - 2rem), 520px);
    max-height: calc(100dvh - 2rem);
    margin: auto;
    padding: var(--space-6);
    border: none;
    border-radius: var(--radius-xl);
    background: var(--card-face);
    box-shadow: var(--shadow-modal);
    color: var(--text-on-light);
    overflow: auto;
}

.send-confirm-dialog::backdrop {
    background: rgba(7, 35, 35, 0.76);
    backdrop-filter: blur(5px);
}

.send-confirm-dialog h2 {
    margin: var(--space-2) 0;
}

.send-confirm-art {
    font-size: 2rem;
}

.send-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-3);
    margin-top: var(--space-5);
}

.send-confirm-actions form {
    margin: 0;
}

/* ============================================
   NARROW SCREENS
   ============================================ */

@media (max-width: 768px) {
    html {
        scroll-padding-top: 5rem;
    }

    #main-content {
        min-height: calc(100vh - 64px);
    }

    .journey-feedback {
        padding: var(--space-4);
    }

    .feedback-actions {
        align-items: stretch;
        flex-direction: column;
    }

    .feedback-actions .btn {
        width: 100%;
    }

    .feedback-summary-heading {
        align-items: flex-start;
        flex-direction: column;
    }

    .send-confirm-actions {
        align-items: stretch;
        flex-direction: column;
    }

    .send-confirm-actions form,
    .send-confirm-actions .btn {
        width: 100%;
    }
}

@media (max-width: 480px) {
    .page-header .event-detail-item,
    .wishlist-header .event-detail-item {
        display: grid;
        grid-template-columns: 26px minmax(0, 1fr);
        column-gap: var(--space-3);
        row-gap: 2px;
        align-items: start;
    }

    .page-header .event-detail-item .detail-icon,
    .wishlist-header .event-detail-item .detail-icon {
        grid-row: 1 / span 2;
    }

    .page-header .event-detail-item .detail-label,
    .page-header .event-detail-item .detail-value,
    .wishlist-header .event-detail-item .detail-label,
    .wishlist-header .event-detail-item .detail-value {
        grid-column: 2;
        min-width: 0;
    }

    .access-status {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
    }

    .access-status-badge {
        width: 100%;
        line-height: 1.35;
    }
}

/* ============================================
   REDUCED MOTION

   The token file already collapses the durations; this removes the ambient
   loops that do not read from a token.
   ============================================ */

@media (prefers-reduced-motion: reduce) {
    .festive-snow {
        display: none;
    }
}
