/* ==========================================================================
   Reusable presentation kit
   --------------------------------------------------------------------------
   Styles for the components under Components/ that any public page can reuse.
   Kept out of brand.css, which is already 4,000 lines of page-specific rules
   and is where this would immediately get lost.

   Everything here reads tokens from brand.css :root and defines no colours of
   its own, so a palette change still happens in exactly one place.
   ========================================================================== */

/* --- Reveal: scroll-triggered entrances ---------------------------------- */

/* The hidden starting state is deliberately scoped to .upcsg-motion, which the
   inline script in index.html sets only when the browser supports the observer,
   and removes again if the module fails to load. Unscoped, a blocked script would
   leave every section below the hero permanently invisible â€” the animation is
   decoration, so its absence must cost nothing. */
.upcsg-motion .upcsg-reveal {
    opacity: 0;
    transition:
        opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
        transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}

.upcsg-motion .upcsg-reveal--up { transform: translateY(28px); }
.upcsg-motion .upcsg-reveal--fade { transform: none; }
.upcsg-motion .upcsg-reveal--scale { transform: scale(0.95); }
.upcsg-motion .upcsg-reveal--left { transform: translateX(-32px); }
.upcsg-motion .upcsg-reveal--right { transform: translateX(32px); }

.upcsg-motion .upcsg-reveal.is-revealed {
    opacity: 1;
    transform: none;
}

/* The --left and --right entrances start 32px outside their column, which pushes the
   document 16px wider than the viewport. That is not a flicker: an element only loses
   the offset once it has been scrolled to, so the horizontal scrollbar sits there from
   load until the reader has reached the last one.

   clip, not hidden: hidden would make this a scroll container and break position:sticky
   for every descendant. */
.upcsg-main,
.upcsg-page {
    overflow-x: clip;
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-motion .upcsg-reveal {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* --- CosmicImage --------------------------------------------------------- */

.upcsg-cosmic {
    position: relative;
    display: block;
    overflow: hidden;
    border-radius: var(--upcsg-radius);
    background: rgba(22, 17, 58, 0.6);
    isolation: isolate;
}

.upcsg-cosmic__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* The generated plate. Two brand hues on an angle, with a soft light source so it
   reads as depth rather than as a flat swatch. */
.upcsg-cosmic--plate {
    background-image:
        radial-gradient(120% 90% at 22% 18%, rgba(246, 255, 233, 0.22), transparent 55%),
        linear-gradient(
            var(--plate-angle, 45deg),
            var(--plate-a, #53257E),
            var(--plate-b, #290087));
}

/* Grain over the gradient. Flat gradients look like placeholders; a little noise
   reads as a printed plate. Pure CSS so it costs no request. */
.upcsg-cosmic--plate::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        repeating-linear-gradient(
            115deg,
            rgba(246, 255, 233, 0.05) 0 1px,
            transparent 1px 4px);
    opacity: 0.55;
    pointer-events: none;
}

.upcsg-cosmic__mark {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
}

.upcsg-cosmic__crest {
    width: 42%;
    max-width: 5.5rem;
    opacity: 0.75;
    filter: drop-shadow(0 4px 18px rgba(6, 3, 24, 0.5));
}

.upcsg-cosmic__initials {
    font-family: var(--upcsg-font-heading);
    font-weight: 700;
    font-size: clamp(1.1rem, 4cqi, 2.4rem);
    letter-spacing: 0.06em;
    color: var(--upcsg-honeydew-white);
    text-shadow: 0 2px 14px rgba(6, 3, 24, 0.55);
}

/* Sized from the plate's own width, so one component works at 44px in a face pile
   and at 400px in a hero without a size parameter. */
.upcsg-cosmic { container-type: inline-size; }

.upcsg-cosmic__badge {
    position: absolute;
    top: 0.7rem;
    left: 0.7rem;
    z-index: 2;
    padding: 0.25rem 0.6rem;
    border-radius: 999px;
    background: rgba(6, 3, 24, 0.72);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(246, 255, 233, 0.16);
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-cosmic__overlay {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    z-index: 2;
    padding: 1.4rem 1.1rem 1rem;
    background: linear-gradient(to top, rgba(6, 3, 24, 0.9), transparent);
}

/* --- SectionHeading ------------------------------------------------------ */

.upcsg-sechead {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.25rem 2rem;
    margin-bottom: 2.5rem;
}

.upcsg-sechead__text { max-width: 46rem; }

.upcsg-sechead__lede { margin-top: 0.85rem; margin-bottom: 0; }

.upcsg-sechead__action { flex-shrink: 0; }

.upcsg-title-xl--center { text-align: center; }

.upcsg-star--tiny {
    display: inline-block;
    width: 0.6rem;
    height: 0.6rem;
    margin-right: 0.4rem;
    vertical-align: baseline;
}

/* --- StatCounter --------------------------------------------------------- */

.upcsg-stat__suffix { font-size: 0.6em; vertical-align: super; }

.upcsg-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- EventCard ----------------------------------------------------------- */

.upcsg-eventcard {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: var(--upcsg-radius);
    border: var(--upcsg-hairline);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.5), rgba(22, 17, 58, 0.75));
    text-decoration: none;
    color: inherit;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease,
        border-color 0.35s ease;
}

.upcsg-eventcard:hover,
.upcsg-eventcard:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(204, 174, 222, 0.45);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-eventcard__poster {
    aspect-ratio: 16 / 10;
    border-radius: 0;
}

/* Quiet: flat ink instead of the gradient. The index at the foot of the detail page
   should stay behind the article, not compete with it. */
.upcsg-eventcard--quiet {
    background: var(--upcsg-ink-panel);
    border-color: var(--upcsg-ink-rule);
}

.upcsg-eventcard--quiet:hover,
.upcsg-eventcard--quiet:focus-visible {
    background: var(--upcsg-ink-hover);
    box-shadow: var(--upcsg-shadow-md);
    transform: translateY(-3px);
}

/* Feature: the lead entry, poster beside the text. */
.upcsg-eventcard--feature { flex-direction: row; }

.upcsg-eventcard--feature .upcsg-eventcard__poster {
    flex: 0 0 clamp(10rem, 34%, 22rem);
    aspect-ratio: auto;
}

.upcsg-eventcard--feature .upcsg-eventcard__body {
    flex: 1;
    padding: clamp(1.25rem, 3vw, 2rem);
    align-items: flex-start;
}

.upcsg-eventcard--feature .upcsg-eventcard__title {
    font-family: var(--upcsg-font-display);
    font-size: clamp(1.35rem, 2.8vw, 2rem);
    line-height: 1.2;
}

.upcsg-eventcard__blurb {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.7rem;
    font-size: 0.94rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

.upcsg-eventcard__countdown {
    display: inline-block;
    margin-top: 0.9rem;
    padding: 0.25rem 0.7rem;
    border-radius: 999px;
    border: var(--upcsg-hairline);
    font-family: var(--upcsg-font-heading);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
}

.upcsg-eventcard__countdown--confirmed { color: var(--upcsg-cosmic-lavender); }
.upcsg-eventcard__countdown--pending { color: var(--upcsg-liquid-chrome-gold); }
.upcsg-eventcard__countdown--received { color: var(--upcsg-periwinkle); opacity: 0.8; }

@media (max-width: 46rem) {
    .upcsg-eventcard--feature { flex-direction: column; }

    .upcsg-eventcard--feature .upcsg-eventcard__poster {
        flex: none;
        aspect-ratio: 16 / 10;
    }
}

.upcsg-eventcard__body {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.1rem 1.25rem;
}

.upcsg-eventcard__text { flex: 1; min-width: 0; }

.upcsg-eventcard__title {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1.3;
    color: var(--upcsg-honeydew-white);
}

.upcsg-eventcard__meta {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.85rem;
    color: var(--upcsg-periwinkle);
}

.upcsg-eventcard__arrow {
    flex-shrink: 0;
    font-size: 1.2rem;
    color: var(--upcsg-liquid-chrome-gold);
    transition: transform 0.3s ease;
}

.upcsg-eventcard:hover .upcsg-eventcard__arrow { transform: translateX(5px); }

/* --- CMS tables on a phone ----------------------------------------------- *
   MudBlazor already stacks a table below 600px: each cell becomes a full-width
   row with its DataLabel printed in front. What it does not do is say where one
   record stops and the next starts - eleven people came out as fifty-five
   identical bordered lines - or drop the cells that only made sense as columns.
 * ------------------------------------------------------------------------- */

@media (max-width: 600px) {
    /* Each record becomes a card. Without this the only separator between two
       people is the same hairline that sits between their name and their role. */
    .upcsg-datatable .mud-table-body .mud-table-row {
        display: block;
        margin-bottom: 0.7rem;
        border: 1px solid var(--upcsg-ink-rule);
        border-radius: 12px;
        background: var(--upcsg-ink-panel);
        overflow: hidden;
    }

    /* Group headings inside the table are a label, not a record. */
    .upcsg-datatable .mud-table-body .mud-table-row:has(> td:only-child) {
        margin-bottom: 0;
        border: none;
        border-radius: 0;
        background: none;
    }

    /* The divider goes on the top of each field rather than the bottom, so a hidden
       last cell - the chevron below - cannot leave a rule floating above the card's
       own edge. Order-independent, unlike :last-child. */
    .upcsg-datatable .mud-table-body .mud-table-cell {
        border-bottom: none;
        border-top: 1px solid var(--upcsg-ink-rule);
    }

    .upcsg-datatable .mud-table-body .mud-table-cell:first-child {
        border-top: none;
    }

    /* A chevron is a column affordance: it said "this row opens" when the row was
       a line. Stacked, it becomes a labelless strip under every record saying
       nothing - and the whole card is tappable anyway. */
    .upcsg-datatable__chevron {
        display: none !important;
    }

    /* Totals lost their pairing when the colspan collapsed: the caption and the
       amount landed on two separate lines. Put them back on one. */
    .upcsg-recordtable .mud-table-foot .mud-table-row {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
    }

    .upcsg-recordtable .mud-table-foot .mud-table-cell {
        border-bottom: none;
    }
}

/* --- Order age (orders queue) -------------------------------------------- */

.upcsg-age {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-size: 0.85rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--upcsg-text);
}

/* An unattended order past a few days. Gold rather than red: it wants an officer,
   it is not an error, and the queue would be a wall of alarm otherwise. */
.upcsg-age--stale {
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-age--stale::after {
    content: "";
    display: inline-block;
    width: 0.4rem;
    height: 0.4rem;
    margin-left: 0.4rem;
    vertical-align: 0.1em;
    border-radius: 50%;
    background: currentColor;
}

/* --- CMS repeater rows (member achievements, contacts) ------------------- */

.upcsg-repeater__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 7rem auto;
    gap: 0.65rem;
    align-items: start;
    margin-bottom: 0.65rem;
}

.upcsg-repeater__year { width: 7rem; }

.upcsg-repeater__kind { width: 100%; }

/* The kind select leads the contact row, so that row's first column is the narrow one. */
.upcsg-repeater__row:has(.upcsg-repeater__kind) {
    grid-template-columns: 9rem minmax(0, 1fr) auto;
}

/* On a phone the row stops being a grid entirely. The earlier attempt moved the
   year and kind columns by class, but those classes are handed to MudSelect and
   MudNumericField, which put them on an inner element rather than on the grid
   child - so the rules addressed nothing and the row stayed at 66px and 229px.
   Stacking every child needs no knowledge of where a class ended up. */
@media (max-width: 40rem) {
    .upcsg-repeater__row,
    .upcsg-repeater__row:has(.upcsg-repeater__kind) {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }

    .upcsg-repeater__year,
    .upcsg-repeater__kind {
        width: 100%;
    }

    /* The delete button is the last child and should not be a full-width bar. */
    .upcsg-repeater__row > :last-child {
        align-self: flex-end;
    }
}

/* --- OpportunityCard ----------------------------------------------------- */

.upcsg-oppcard {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    border-radius: var(--upcsg-radius);
    border: var(--upcsg-hairline);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.5), rgba(22, 17, 58, 0.75));
    text-decoration: none;
    color: inherit;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease,
        border-color 0.35s ease;
}

.upcsg-oppcard:hover,
.upcsg-oppcard:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(204, 174, 222, 0.45);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-oppcard--featured {
    border-color: rgba(226, 190, 122, 0.4);
}

.upcsg-oppcard__poster {
    aspect-ratio: 16 / 10;
    border-radius: 0;
}

.upcsg-oppcard__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 0.55rem;
    padding: 1.1rem 1.25rem 1.25rem;
}

.upcsg-oppcard__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.upcsg-oppcard__title {
    display: block;
    margin: 0;
    font-family: var(--upcsg-font-heading);
    font-weight: 600;
    font-size: 1.05rem;
    line-height: 1.3;
    color: var(--upcsg-honeydew-white);
}

.upcsg-oppcard__org {
    display: block;
    margin: 0;
    font-size: 0.85rem;
    color: var(--upcsg-periwinkle);
}

.upcsg-oppcard__blurb {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
    font-size: 0.94rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

.upcsg-oppcard__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: auto;
    padding-top: 0.85rem;
}

.upcsg-oppcard__deadline {
    font-family: var(--upcsg-font-heading);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-oppcard__arrow {
    flex-shrink: 0;
    font-size: 1.2rem;
    color: var(--upcsg-liquid-chrome-gold);
    transition: transform 0.3s ease;
}

.upcsg-oppcard:hover .upcsg-oppcard__arrow { transform: translateX(5px); }

/* --- Opportunity detail -------------------------------------------------- */

/* Masthead. Not the event hero: an opportunity rarely ships with artwork worth
   going full-bleed on, so the band supplies its own light - flare, sparkles,
   metallic-silk title - and the poster, when there is one, floats over the lower
   edge as a lifted plate rather than sitting behind a scrim. */
.upcsg-oppmast {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: clamp(6.5rem, 12vw, 9rem) 0 clamp(2rem, 5vw, 3.5rem);
    border-bottom: var(--upcsg-hairline);
    background-color: var(--upcsg-bg);
    background-image:
        radial-gradient(70% 90% at 10% 0%, rgba(162, 83, 184, 0.4) 0%, transparent 62%),
        radial-gradient(60% 80% at 92% 100%, rgba(41, 0, 135, 0.5) 0%, transparent 66%),
        linear-gradient(140deg, rgba(83, 37, 126, 0.5) 0%, rgba(22, 17, 58, 0.85) 60%);
}

.upcsg-oppmast__flare {
    width: 26rem;
    height: 26rem;
    top: -8rem;
    left: -6rem;
    background: radial-gradient(circle, rgba(162, 83, 184, 0.55) 0%, transparent 70%);
}

.upcsg-oppmast__inner {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 17rem);
    gap: clamp(1.75rem, 5vw, 3.5rem);
    align-items: end;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding-inline: 1.5rem;
}

.upcsg-oppmast__inner--plain { grid-template-columns: minmax(0, 1fr); }

.upcsg-oppmast__back {
    display: inline-block;
    margin-bottom: 1.5rem;
    font-size: 0.9rem;
}

.upcsg-oppmast__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-bottom: 1.1rem;
}

.upcsg-oppmast__title {
    margin: 0;
    font-family: var(--upcsg-font-display);
    font-size: clamp(2.4rem, 6vw, 4rem);
    line-height: 1.05;
    letter-spacing: -0.01em;
}

.upcsg-oppmast__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 1.25rem;
    margin: 1.25rem 0 0;
}

.upcsg-oppmast__org {
    font-family: var(--upcsg-font-subheading);
    font-size: 1.1rem;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-oppmast__where {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.92rem;
    color: var(--upcsg-periwinkle);
}

/* Hangs below the band so the plate reads as sitting in front of it, not inside it. */
.upcsg-oppmast__plate {
    aspect-ratio: 3 / 4;
    border-radius: var(--upcsg-radius);
    margin-bottom: clamp(-3.5rem, -6vw, -2rem);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-oppdeadline {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: center;
    padding: clamp(1.5rem, 3.5vw, 2.5rem);
    border-radius: 28px;
    margin-top: clamp(2rem, 5vw, 3.5rem);
}

/* The dial is the page's one loud element: a ring showing how much of the
   application window has gone, wrapped around the days that are left. It reads
   as a lens flare rather than a progress bar, which is the house vocabulary. */
.upcsg-dial {
    --upcsg-dial-size: clamp(9rem, 18vw, 12rem);
    --upcsg-dial-track: rgba(246, 255, 233, 0.12);
    --upcsg-dial-fill: var(--upcsg-cosmic-lavender);

    position: relative;
    display: grid;
    place-items: center;
    width: var(--upcsg-dial-size);
    height: var(--upcsg-dial-size);
    flex: none;
    border-radius: 50%;
    background: conic-gradient(
        var(--upcsg-dial-fill) calc(var(--upcsg-dial-progress) * 360deg),
        var(--upcsg-dial-track) 0
    );
}

/* Punches the ring out of the disc, leaving a 6px band. */
.upcsg-dial::before {
    content: "";
    position: absolute;
    inset: 6px;
    border-radius: 50%;
    background:
        radial-gradient(circle at 50% 40%, rgba(162, 83, 184, 0.35) 0%, transparent 70%),
        var(--upcsg-bg);
}

/* The bloom behind the glass. */
.upcsg-dial::after {
    content: "";
    position: absolute;
    inset: -12%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(162, 83, 184, 0.45) 0%, transparent 68%);
    filter: blur(18px);
    z-index: -1;
}

.upcsg-dial__face {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding-inline: 0.75rem;
}

.upcsg-dial__num {
    font-family: var(--upcsg-font-display);
    font-size: clamp(2.5rem, 6vw, 3.75rem);
    line-height: 1;
    color: var(--upcsg-honeydew-white);
}

.upcsg-dial__unit {
    margin-top: 0.4rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    line-height: 1.3;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

/* Urgency is the one thing this panel exists to say, so it drives the colour. */
.upcsg-oppdeadline--urgent { border-color: rgba(246, 200, 117, 0.4); }
.upcsg-oppdeadline--urgent .upcsg-dial { --upcsg-dial-fill: var(--upcsg-cta); }
.upcsg-oppdeadline--urgent .upcsg-dial__num { color: var(--upcsg-cta); }

.upcsg-oppdeadline--soon .upcsg-dial { --upcsg-dial-fill: var(--upcsg-liquid-chrome-gold); }
.upcsg-oppdeadline--soon .upcsg-dial__num { color: var(--upcsg-liquid-chrome-gold); }

.upcsg-oppdeadline--open .upcsg-dial__num { color: var(--upcsg-cosmic-lavender); }

.upcsg-oppdeadline--closed .upcsg-dial { --upcsg-dial-fill: rgba(246, 255, 233, 0.2); }

.upcsg-oppdeadline--closed .upcsg-dial__num {
    font-size: clamp(1.5rem, 3.5vw, 2rem);
    color: var(--upcsg-text-muted);
}

.upcsg-oppdeadline__body {
    display: flex;
    flex-direction: column;
    gap: clamp(1.25rem, 3vw, 1.75rem);
    min-width: 0;
}

.upcsg-oppstages {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.upcsg-oppstages__step {
    position: relative;
    padding-top: 1.1rem;
    border-top: 2px solid rgba(204, 174, 222, 0.16);
}

.upcsg-oppstages__step::before {
    content: "";
    position: absolute;
    top: -0.42rem;
    left: 0;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 999px;
    background: var(--upcsg-space-cadet);
    border: 2px solid rgba(204, 174, 222, 0.35);
}

.upcsg-oppstages__step--done { border-top-color: rgba(204, 174, 222, 0.45); }

.upcsg-oppstages__step--done::before {
    background: var(--upcsg-cosmic-lavender);
    border-color: var(--upcsg-cosmic-lavender);
}

.upcsg-oppstages__step--ahead::before { border-color: var(--upcsg-liquid-chrome-gold); }

.upcsg-oppstages__step--blank { opacity: 0.5; }

.upcsg-oppstages__label {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

.upcsg-oppstages__value {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.95rem;
    color: var(--upcsg-honeydew-white);
}

.upcsg-oppdeadline__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* --- Opportunity body ---------------------------------------------------- */

.upcsg-oppbody {
    max-width: 46rem;
    margin: clamp(2.5rem, 6vw, 4rem) 0 0;
    padding-left: clamp(1rem, 3vw, 2rem);
    border-left: 2px solid rgba(246, 200, 117, 0.35);
}

/* The opening paragraph is the pitch, so it gets set like one. */
.upcsg-oppbody__lead {
    margin: 0;
    font-family: var(--upcsg-font-subheading);
    font-size: clamp(1.15rem, 2.2vw, 1.45rem);
    line-height: 1.55;
    color: var(--upcsg-honeydew-white);
}

.upcsg-oppbody__para {
    margin: 1.25rem 0 0;
    font-size: 1rem;
    line-height: 1.75;
    color: var(--upcsg-periwinkle);
}

@media (max-width: 52rem) {
    .upcsg-oppmast__inner { grid-template-columns: minmax(0, 1fr); }

    .upcsg-oppmast__plate {
        order: -1;
        aspect-ratio: 16 / 10;
        margin-bottom: 0;
        max-width: 20rem;
    }
}

@media (max-width: 46rem) {
    .upcsg-oppdeadline {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
    }

    .upcsg-oppdeadline__body { width: 100%; }

    .upcsg-oppstages { grid-template-columns: minmax(0, 1fr); }
}

/* --- MerchCard ----------------------------------------------------------- */

.upcsg-merchcard {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.upcsg-merchcard:hover,
.upcsg-merchcard:focus-visible { transform: translateY(-6px); }

.upcsg-merchcard__thumb {
    aspect-ratio: 1;
    border: var(--upcsg-hairline);
    transition: box-shadow 0.35s ease, border-color 0.35s ease;
}

.upcsg-merchcard:hover .upcsg-merchcard__thumb {
    border-color: rgba(246, 200, 117, 0.5);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-merchcard__body { padding: 0.9rem 0.2rem 0; }

.upcsg-merchcard__name {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-weight: 600;
    font-size: 0.98rem;
    color: var(--upcsg-honeydew-white);
}

.upcsg-merchcard__price {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    margin-top: 0.3rem;
    font-size: 0.9rem;
}

.upcsg-merchcard__from { color: var(--upcsg-periwinkle); font-size: 0.8rem; }
.upcsg-merchcard__now { color: var(--upcsg-liquid-chrome-gold); font-weight: 600; }
.upcsg-merchcard__was { color: var(--upcsg-periwinkle); text-decoration: line-through; font-size: 0.82rem; }
.upcsg-merchcard__gone { color: var(--upcsg-periwinkle); }

/* A sold-out item stays legible and clickable â€” its page still explains itself â€” but
   stops competing with what can actually be bought. */
.upcsg-merchcard--out .upcsg-merchcard__thumb { opacity: 0.55; }

.upcsg-merchcard__variants {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.6rem;
}

.upcsg-merchcard__cue {
    display: block;
    margin-top: auto;
    padding-top: 0.9rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-merchcard:hover .upcsg-merchcard__cue { color: var(--upcsg-liquid-chrome-gold); }

.upcsg-merchcard--card .upcsg-merchcard__body {
    display: flex;
    flex-direction: column;
    flex: 1;
}

/* Feature: the leading drop, photo beside the copy. */
.upcsg-merchcard--feature {
    flex-direction: row;
    align-items: stretch;
    border: var(--upcsg-hairline);
    border-radius: var(--upcsg-radius);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.45), rgba(22, 17, 58, 0.75));
    overflow: hidden;
}

.upcsg-merchcard--feature:hover { transform: translateY(-4px); }

.upcsg-merchcard--feature .upcsg-merchcard__thumb {
    flex: 0 0 clamp(11rem, 42%, 26rem);
    aspect-ratio: auto;
    border: none;
    border-radius: 0;
}

.upcsg-merchcard--feature .upcsg-merchcard__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(1.5rem, 3.5vw, 2.75rem);
}

.upcsg-merchcard--feature .upcsg-merchcard__name {
    margin-top: 0.35rem;
    font-family: var(--upcsg-font-display);
    font-size: clamp(1.6rem, 3.4vw, 2.4rem);
    line-height: 1.15;
}

.upcsg-merchcard__blurb {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.6rem;
    font-size: 0.98rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

.upcsg-merchcard--feature .upcsg-merchcard__price { font-size: 1.15rem; margin-top: 0.8rem; }

.upcsg-merchcard--feature .upcsg-merchcard__cue { margin-top: 1.25rem; padding-top: 0; }

@media (max-width: 52rem) {
    .upcsg-merchcard--feature { flex-direction: column; }

    .upcsg-merchcard--feature .upcsg-merchcard__thumb {
        flex: none;
        aspect-ratio: 16 / 10;
    }
}

/* --- Contact channels ---------------------------------------------------- */

.upcsg-channel {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 1.5rem 1.4rem 1.35rem;
    border: var(--upcsg-hairline);
    border-radius: var(--upcsg-radius);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.45), rgba(22, 17, 58, 0.75));
    text-decoration: none;
    color: inherit;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease,
        border-color 0.35s ease;
}

.upcsg-channel:hover,
.upcsg-channel:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(204, 174, 222, 0.45);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-channel__icon {
    display: grid;
    place-items: center;
    width: 2.9rem;
    height: 2.9rem;
    margin-bottom: 1rem;
    border-radius: 50%;
    border: var(--upcsg-hairline);
    background: rgba(6, 3, 24, 0.4);
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-channel__tag {
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--upcsg-cosmic-lavender);
}

/* Long addresses must wrap inside the card rather than widening the grid track.
   anywhere, not break-word: an email has no spaces to break at. */
.upcsg-channel__handle {
    margin-top: 0.3rem;
    font-family: var(--upcsg-font-display);
    font-size: 1.25rem;
    line-height: 1.25;
    color: var(--upcsg-honeydew-white);
    overflow-wrap: anywhere;
}

.upcsg-channel__meta {
    margin-top: 0.6rem;
    font-size: 0.92rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

.upcsg-channel__cue {
    margin-top: auto;
    padding-top: 1rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-channel:hover .upcsg-channel__cue { color: var(--upcsg-liquid-chrome-gold); }

/* Two buttons in a closing CTA, stacking on narrow screens. */
.upcsg-closing__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    justify-content: center;
}

/* --- Merch gallery ------------------------------------------------------- */

/* The main frame is a CosmicImage now, so it carries the plate itself rather than
   wrapping a bare img that had nothing behind it when the URL was dead. */
.upcsg-gallery__main {
    aspect-ratio: 1;
    width: 100%;
    border: var(--upcsg-hairline);
}

.upcsg-gallery__thumb .upcsg-cosmic {
    width: 100%;
    height: 100%;
    border-radius: inherit;
}

/* --- FacePile ------------------------------------------------------------ */

.upcsg-facepile {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem; /* replaces whatever negative-margin overlap you had */

    /* Vertical padding leaves room for the selected face to lift without being clipped. */
    padding: 0.75rem 0.6rem;
}

/* MudTooltip wraps each face in an element of its own, so the flex items here are the
   wrappers and not the buttons â€” flex rules on .upcsg-facepile__face never reach the
   thing being sized, and the wrappers would shrink the faces rather than wrap them. */
.upcsg-facepile > .mud-tooltip-root {
    flex: 0 0 auto;
    display: inline-flex;
}

.upcsg-facepile__face {
    /* A real <button> for Tab and Enter; this first group undoes the browser's default
       chrome for one. */
    appearance: none;
    padding: 0;
    background: none;
    font: inherit;
    color: inherit;
    cursor: pointer;

    width: clamp(2.6rem, 6vw, 3.4rem);
    aspect-ratio: 1;
    border-radius: 50%;
    margin-left: -0.6rem;
    border: 2px solid var(--upcsg-midnight-indigo);
    box-shadow: var(--upcsg-shadow-sm);

    /* Without this the faces are compressed to fit the row and the strip never
       overflows, so it never scrolls. */
    flex: 0 0 auto;

    /* Later faces sit on top of earlier ones, so the row overlaps in reading order
       instead of the last one being buried. */
    /* Only needs to sit below the hover and selected states; the faces no longer overlap,
       so there is nothing to order them against. */
    z-index: 1;
    position: relative;
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1),
                box-shadow 0.3s ease,
                border-color 0.3s ease;
}

.upcsg-facepile__portrait {
    width: 100%;
    height: 100%;
    border-radius: 50%;

    /* The portrait must not take the pointer, or a drag starting on an image never
       reaches the button underneath. */
    pointer-events: none;
}

.upcsg-facepile__face:hover,
.upcsg-facepile__face:focus-visible {
    transform: translateY(-6px) scale(1.08);
    z-index: 30;
}

.upcsg-facepile__face:focus-visible {
    outline: 2px solid var(--upcsg-liquid-chrome-gold);
    outline-offset: 3px;
}

/* Whoever is in the plate beside the strip. Lifted and ringed rather than just
   brightened â€” in a row of round portraits at this size, a colour shift alone does not
   read as "this one". */
.upcsg-facepile__face--on {
    transform: translateY(-6px) scale(1.12);
    border-color: var(--upcsg-liquid-chrome-gold);
    box-shadow: 0 0 0 2px rgba(246, 200, 117, 0.35), var(--upcsg-shadow-md);
    z-index: 31;
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-facepile {
        scroll-behavior: auto;
    }

    .upcsg-facepile__face {
        transition: none;
    }
}

/* --- Marquee ------------------------------------------------------------- */

.upcsg-marquee {
    overflow: hidden;
    padding: 1.1rem 0;
    border-top: var(--upcsg-hairline);
    border-bottom: var(--upcsg-hairline);

    /* Fades at both ends so items enter and leave instead of being clipped. */
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.upcsg-marquee__track {
    display: flex;
    width: max-content;
    animation: upcsg-marquee-scroll var(--marquee-duration, 40s) linear infinite;
}

.upcsg-marquee__run { display: flex; align-items: center; }

.upcsg-marquee__item {
    padding: 0 1.1rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--upcsg-periwinkle);
}

.upcsg-marquee__sep { flex-shrink: 0; opacity: 0.6; }

.upcsg-marquee:hover .upcsg-marquee__track { animation-play-state: paused; }

@keyframes upcsg-marquee-scroll {
    from { transform: translateX(0); }

    /* Exactly half: the track holds two identical runs, so at -50% the second sits
       where the first began and the loop has no seam. */
    to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-marquee__track { animation: none; }
}

.upcsg-marquee--hero {
    border-top: none;
    background: linear-gradient(180deg, rgba(22, 17, 58, 0.9), rgba(22, 17, 58, 0));
}

/* --- Page layout: grids, features, empties ------------------------------- */

.upcsg-cardgrid {
    display: grid;
    gap: 1.5rem;
}

/* auto-fit rather than a fixed count: with two merch items the row fills the width
   instead of leaving two dead columns, which is the state the store is usually in. */
.upcsg-cardgrid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); }
.upcsg-cardgrid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }

.upcsg-skeleton {
    border-radius: var(--upcsg-radius);
    background-color: rgba(82, 38, 87, 0.35) !important;
}

/* Cards sit inside a Reveal wrapper, so the wrapper is the grid item and the card is
   only as tall as its own text. Roles and quotes vary in length, so a row ended up with
   cards of four different heights and ragged bottom edges. Making the wrapper a flex
   container passes the stretched row height through to the card itself. */
.upcsg-cardgrid > .upcsg-reveal,
.upcsg-memberpile > .upcsg-reveal {
    display: flex;
}

.upcsg-cardgrid > .upcsg-reveal > *,
.upcsg-memberpile > .upcsg-reveal > * {
    flex: 1;
}

/* Feature band: text one side, a large plate the other. Alternating the sides is what
   gives the page a rhythm the old stack of identical bands never had. */
.upcsg-feature {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
}

.upcsg-feature--reverse .upcsg-feature__visual { order: -1; }

/* Below the breakpoint the plate always follows the text, whichever side it takes on
   desktop â€” a picture above its own heading reads as belonging to the section before. */
@media (max-width: 62rem) {
    .upcsg-feature--reverse .upcsg-feature__visual { order: 0; }
}

.upcsg-feature__plate {
    aspect-ratio: 4 / 5;
    width: 100%;
    box-shadow: var(--upcsg-shadow-lg);
}

/* Officer switcher on the home page. The stage is the positioning context for the
   outgoing plate, which is taken out of flow so the incoming plate sizes the column. */
.upcsg-officerstage {
    position: relative;
}

.upcsg-officerstage__current {
    animation: upcsg-officer-in 0.45s ease;
}

.upcsg-officerstage__leaving {
    position: absolute;
    inset: 0;
    animation: upcsg-officer-out 0.45s ease;
    pointer-events: none;
}

@keyframes upcsg-officer-in {
    from { opacity: 0; transform: translateX(-2.5rem); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes upcsg-officer-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(2.5rem); }
}

/* No slide for anyone who asked the OS to reduce motion; the incoming plate just
   appears, and the outgoing one is hidden at once rather than lingering on top. */
@media (prefers-reduced-motion: reduce) {
    .upcsg-officerstage__current { animation: none; }
    .upcsg-officerstage__leaving { display: none; }
}

.upcsg-feature__plate-role {
    margin: 0;
    font-family: var(--upcsg-font-heading);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-feature__plate-name {
    margin: 0.2rem 0 0;
    font-family: var(--upcsg-font-display);
    font-size: 1.5rem;
    line-height: 1.2;
    color: var(--upcsg-honeydew-white);
}

.upcsg-statrow {
    display: flex;
    flex-wrap: wrap;
    gap: 2.5rem;
    margin-top: 2.25rem;
    padding-top: 1.75rem;
    border-top: var(--upcsg-hairline);
}

.upcsg-empty {
    display: grid;
    justify-items: center;
    gap: 1rem;
    padding: 3.5rem 1.5rem;
    border: 1px dashed rgba(246, 255, 233, 0.16);
    border-radius: var(--upcsg-radius);
    text-align: center;
    color: var(--upcsg-periwinkle);
}

.upcsg-empty img { width: 3.5rem; opacity: 0.4; }
.upcsg-empty p { margin: 0; max-width: 32rem; }

/* When nothing at all is published the empty state is the page, so it gets room to
   be a statement rather than a note squeezed under a heading. */
.upcsg-empty--tall { padding: clamp(3.5rem, 10vw, 6rem) 1.5rem; gap: 1.25rem; }
.upcsg-empty--tall img { width: 5rem; }

/* --- Hall of Fame ------------------------------------------------------- */

.upcsg-achcard {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: var(--upcsg-radius);
    border: var(--upcsg-hairline);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.45), rgba(22, 17, 58, 0.75));
    text-decoration: none;
    color: inherit;
    height: 100%;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease,
        border-color 0.35s ease;
}

.upcsg-achcard:hover,
.upcsg-achcard:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(246, 200, 117, 0.45);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-achcard__media {
    aspect-ratio: 16 / 10;
    border-radius: 0;
}

.upcsg-achcard__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 1.15rem 1.25rem 1.35rem;
}

.upcsg-achcard__kicker {
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
    min-height: 1rem;
}

.upcsg-achcard__title {
    margin-top: 0.4rem;
    font-family: var(--upcsg-font-display);
    font-size: 1.3rem;
    line-height: 1.25;
    color: var(--upcsg-honeydew-white);
}

/* Entries run to several hundred words; the standfirst is the opening paragraph, so
   without a clamp one long opener sets the height of every card beside it. */
.upcsg-achcard__standfirst {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.55rem;
    font-size: 0.92rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

/* Pushed to the bottom so the cue sits on one line across a row of uneven copy. */
.upcsg-achcard__cue {
    margin-top: auto;
    padding-top: 0.9rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-achcard:hover .upcsg-achcard__cue { color: var(--upcsg-liquid-chrome-gold); }

/* Lead: media beside the copy. */
.upcsg-achcard--lead { flex-direction: row; }

.upcsg-achcard--lead .upcsg-achcard__media {
    flex: 0 0 clamp(11rem, 42%, 26rem);
    aspect-ratio: auto;
}

.upcsg-achcard--lead .upcsg-achcard__body {
    justify-content: center;
    padding: clamp(1.5rem, 3.5vw, 2.75rem);
}

.upcsg-achcard--lead .upcsg-achcard__title {
    font-size: clamp(1.6rem, 3.4vw, 2.4rem);
}

.upcsg-achcard--lead .upcsg-achcard__standfirst {
    -webkit-line-clamp: 4;
    line-clamp: 4;
    font-size: 1rem;
}

.upcsg-achcard--lead .upcsg-achcard__cue { margin-top: 1.25rem; padding-top: 0; }

@media (max-width: 52rem) {
    .upcsg-achcard--lead { flex-direction: column; }

    .upcsg-achcard--lead .upcsg-achcard__media {
        flex: none;
        aspect-ratio: 16 / 10;
    }
}

/* The grid item is the Reveal wrapper, so the card needs the stretched height passed
   through to keep a row's bottom edges level. */
.upcsg-recordgrid > .upcsg-reveal { display: flex; }
.upcsg-recordgrid > .upcsg-reveal > * { flex: 1; }

.upcsg-filterrow { margin-bottom: 1.75rem; }

/* --- Events page: calendar rail beside the listing ----------------------- */

.upcsg-eventslayout {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 3rem);
    align-items: start;
}

.upcsg-eventslayout__rail { position: sticky; top: 1.5rem; }

.upcsg-calcard {
    padding: 1.25rem;
    border: var(--upcsg-hairline);
    border-radius: var(--upcsg-radius);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.42), rgba(22, 17, 58, 0.72));
}

.upcsg-calcard__head { margin-bottom: 1rem; }

/* The month-stepping variant: heading on the left, arrows pinned right. */
.upcsg-calcard__head--nav {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
}

.upcsg-calcard__title {
    margin: 0.2rem 0 0;
    font-family: var(--upcsg-font-display);
    font-size: 1.6rem;
    line-height: 1.1;
    color: var(--upcsg-honeydew-white);
}

.upcsg-calcard__note {
    margin: 1rem 0 0;
    font-size: 0.78rem;
    color: var(--upcsg-text-muted);
}

.upcsg-calnav {
    display: flex;
    gap: 0.35rem;
    flex: none;
}

.upcsg-calnav__btn {
    width: 2rem;
    height: 2rem;
    display: grid;
    place-items: center;
    padding: 0;
    font: inherit;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--upcsg-text);
    background: rgba(246, 255, 233, 0.04);
    border: 1px solid rgba(204, 174, 222, 0.24);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}

.upcsg-calnav__btn:hover:not(:disabled) {
    transform: translateY(-1px);
    border-color: var(--upcsg-cosmic-lavender);
    background: rgba(204, 174, 222, 0.12);
}

.upcsg-calnav__btn:focus-visible {
    outline: 2px solid var(--upcsg-cta);
    outline-offset: 2px;
}

/* Disabled means the range ends here, so it stays visible rather than vanishing -
   the reader can see there is nothing further to page to. */
.upcsg-calnav__btn:disabled {
    opacity: 0.3;
    cursor: default;
}

.upcsg-eventlist { display: grid; gap: 1.25rem; }

/* Marks the day the reader just picked, so the scroll lands somewhere obvious
   instead of dumping them at an unremarkable card. */
.upcsg-eventlist__hit,
.upcsg-cardhit {
    position: relative;
    border-radius: var(--upcsg-radius);
    outline: 2px solid rgba(246, 200, 117, 0.55);
    outline-offset: 4px;
}

/* The card inside sets the height; without this the outline hugs a taller box than
   the card in a grid row whose other cards are longer. */
.upcsg-cardhit { height: 100%; }

/* The rail stops being a rail once it would be narrower than the calendar it holds. */
@media (max-width: 60rem) {
    .upcsg-eventslayout { grid-template-columns: minmax(0, 1fr); }
    .upcsg-eventslayout__rail { position: static; }
}

/* --- Opportunities planner: a full-width wall calendar ------------------- *
   Deliberately not the events rail. Events fit one month in a glanceable
   corner because there are a handful of them on known dates; deadlines are
   the whole point here, so they get the width and are legible by name in the
   cell rather than reduced to a dot you have to decode.
 * ------------------------------------------------------------------------ */

.upcsg-planner {
    --upcsg-planner-cell: clamp(4.5rem, 8.5vw, 7.5rem);

    border: var(--upcsg-hairline);
    border-radius: 28px;
    background: linear-gradient(180deg, rgba(83, 37, 126, 0.2) 0%, rgba(22, 17, 58, 0.42) 100%);
    box-shadow: inset 0 1px 0 rgba(246, 255, 233, 0.07);
    padding: clamp(1.1rem, 2.6vw, 2rem);
    overflow: hidden;
}

.upcsg-planner__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: clamp(1rem, 2.4vw, 1.75rem);
}

.upcsg-planner__month {
    margin: 0.25rem 0 0;
    font-family: var(--upcsg-font-display);
    font-size: clamp(2rem, 5vw, 3.25rem);
    line-height: 1;
    color: var(--upcsg-honeydew-white);
}

.upcsg-planner__month small {
    font-family: var(--upcsg-font-heading);
    font-size: 0.4em;
    letter-spacing: 0.14em;
    color: var(--upcsg-text-muted);
    margin-left: 0.6rem;
    vertical-align: middle;
}

.upcsg-planner__controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.upcsg-planner__grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0.4rem;
}

.upcsg-planner__dow {
    font-family: var(--upcsg-font-heading);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
    text-align: left;
    padding: 0 0 0.5rem 0.35rem;
}

.upcsg-planner__blank {
    min-height: var(--upcsg-planner-cell);
    border-radius: 14px;
    background: rgba(246, 255, 233, 0.015);
}

.upcsg-planner__day {
    display: flex;
    flex-direction: column;

    /* The marked cells are buttons, and the UA stylesheet centres a button's flex
       children. Left-aligned is what a planner cell wants, and without this the
       entries shrink to their content instead of filling the cell. */
    align-items: stretch;
    gap: 0.25rem;
    min-height: var(--upcsg-planner-cell);
    padding: 0.45rem 0.45rem 0.5rem;
    border: 1px solid rgba(204, 174, 222, 0.12);
    border-radius: 14px;
    background: rgba(246, 255, 233, 0.03);
    text-align: left;
    font: inherit;
    color: var(--upcsg-text-muted);
}

.upcsg-planner__day--marked {
    cursor: pointer;
    color: var(--upcsg-text);
    border-color: rgba(204, 174, 222, 0.3);
    background: linear-gradient(160deg, rgba(162, 83, 184, 0.2), rgba(83, 37, 126, 0.16));
    transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}

.upcsg-planner__day--marked:hover {
    transform: translateY(-2px);
    border-color: var(--upcsg-cosmic-lavender);
    box-shadow: var(--upcsg-shadow-md);
}

.upcsg-planner__day--marked:focus-visible {
    outline: 2px solid var(--upcsg-cta);
    outline-offset: 2px;
}

.upcsg-planner__day--today .upcsg-planner__num {
    color: var(--upcsg-space-cadet);
    background: var(--upcsg-cta);
}

.upcsg-planner__day--selected {
    border-color: var(--upcsg-cta);
    box-shadow: inset 0 0 0 1px var(--upcsg-cta);
}

.upcsg-planner__num {
    display: grid;
    place-items: center;
    width: 1.6rem;
    height: 1.6rem;
    flex: none;
    border-radius: 8px;
    font-family: var(--upcsg-font-heading);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1;
}

.upcsg-planner__entries {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

/* Two-line clamp keeps a long title from pushing the cell taller than its row. */
.upcsg-planner__entry {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    padding: 0.14rem 0.3rem;
    border-left: 2px solid var(--upcsg-liquid-chrome-gold);
    border-radius: 3px;
    background: rgba(226, 190, 122, 0.12);
    font-size: 0.68rem;
    line-height: 1.25;
    color: var(--upcsg-honeydew-white);
}

.upcsg-planner__entry--happens {
    border-left-color: var(--upcsg-cosmic-lavender);
    background: rgba(204, 174, 222, 0.12);
}

.upcsg-planner__more {
    font-family: var(--upcsg-font-heading);
    font-size: 0.62rem;
    letter-spacing: 0.06em;
    color: var(--upcsg-text-muted);
    padding-left: 0.3rem;
}

.upcsg-planner__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 1.15rem;
    margin-top: 1.25rem;
    font-size: 0.76rem;
    color: var(--upcsg-text-muted);
}

.upcsg-planner__legend span {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.upcsg-planner__legend i {
    width: 0.85rem;
    height: 0.85rem;
    flex: none;
    border-radius: 3px;
    border-left: 2px solid var(--upcsg-liquid-chrome-gold);
    background: rgba(226, 190, 122, 0.12);
}

.upcsg-planner__legend i.is-happens {
    border-left-color: var(--upcsg-cosmic-lavender);
    background: rgba(204, 174, 222, 0.12);
}

.upcsg-planner__legend i.is-today {
    border: none;
    border-radius: 5px;
    background: var(--upcsg-cta);
}

.upcsg-planner__summary { margin-left: auto; }

/* Below this the cells cannot hold a readable title, so the entries collapse to
   bars. The grid stays a month - a seven-column shape people can read at a
   glance is worth more than titles that would each wrap to four lines. */
@media (max-width: 52rem) {
    .upcsg-planner { --upcsg-planner-cell: 3.4rem; }

    .upcsg-planner__day { padding: 0.3rem; gap: 0.2rem; }

    .upcsg-planner__num {
        width: 1.35rem;
        height: 1.35rem;
        font-size: 0.72rem;
    }

    .upcsg-planner__entry {
        height: 0.28rem;
        padding: 0;
        border-left: none;
        border-radius: 999px;
        font-size: 0;
        line-height: 0;
        background: var(--upcsg-liquid-chrome-gold);
    }

    .upcsg-planner__entry--happens { background: var(--upcsg-cosmic-lavender); }

    .upcsg-planner__more { display: none; }
}

/* --- Event detail hero --------------------------------------------------- */

.upcsg-eventhero {
    position: relative;
    isolation: isolate;
    min-height: clamp(20rem, 46vh, 30rem);
    display: flex;
    align-items: flex-end;
}

.upcsg-eventhero__art {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
    z-index: -2;
}

.upcsg-eventhero__scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(
        to top,
        var(--upcsg-midnight-indigo) 2%,
        rgba(22, 17, 58, 0.82) 32%,
        rgba(22, 17, 58, 0.35) 68%,
        rgba(22, 17, 58, 0.15) 100%);
}

.upcsg-eventhero__inner {
    width: min(100%, 1180px);
    margin: 0 auto;
    padding: clamp(2rem, 6vw, 4rem) 1rem clamp(1.75rem, 4vw, 2.75rem);
}

.upcsg-eventhero__title {
    margin: 0.4rem 0 1rem;
    font-family: var(--upcsg-font-display);
    font-size: clamp(2rem, 6vw, 3.6rem);
    line-height: 1.08;
    color: var(--upcsg-honeydew-white);
    text-shadow: 0 4px 32px rgba(6, 3, 24, 0.75);
}

.upcsg-eventbody--wide {
    max-width: 46rem;
    margin-bottom: 1rem;
}

/* Closing CTA: centred, with its own glow, so the page ends on a swell rather than on
   another band identical to the four above it. */
.upcsg-closing {
    position: relative;
    overflow: hidden;
    border-radius: var(--upcsg-radius);
    border: var(--upcsg-hairline);
    background: radial-gradient(120% 140% at 50% 0%, rgba(82, 38, 87, 0.75), rgba(22, 17, 58, 0.4));
}

.upcsg-closing__inner {
    position: relative;
    z-index: 1;
    display: grid;
    justify-items: center;
    text-align: center;
    gap: 0.4rem;
    padding: clamp(2.5rem, 6vw, 4.5rem) 1.5rem;
}

.upcsg-closing__inner .upcsg-lede { max-width: 40rem; margin-bottom: 1.75rem; }

.upcsg-closing__flare {
    position: absolute;
    top: -40%;
    left: 50%;
    transform: translateX(-50%);
    width: min(38rem, 90%);
    aspect-ratio: 1;
    background: radial-gradient(circle, rgba(162, 83, 184, 0.5), transparent 62%);
    pointer-events: none;
}

/* --- Member roster ------------------------------------------------------- */

/* auto-fill, not auto-fit. auto-fit collapses the empty tracks and stretches what is
   left, so the Representatives committee â€” which has exactly one member â€” would render
   as a single card spanning the full page width. auto-fill keeps the column rhythm and
   lets a short row simply end. */
.upcsg-memberpile {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
    gap: 1.5rem;
    margin-bottom: 2.5rem;
}

.upcsg-membercard {
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: 0;
    border: var(--upcsg-hairline);
    border-radius: var(--upcsg-radius);
    background: linear-gradient(180deg, rgba(82, 38, 87, 0.42), rgba(22, 17, 58, 0.72));
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease,
        border-color 0.35s ease;
}

.upcsg-membercard:hover,
.upcsg-membercard:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(204, 174, 222, 0.45);
    box-shadow: var(--upcsg-shadow-lg), var(--upcsg-bloom);
}

.upcsg-membercard__portrait {
    aspect-ratio: 4 / 5;
    border-radius: 0;
    width: 100%;
}

.upcsg-membercard__body {
    display: block;
    padding: 1rem 1.1rem 0.4rem;
    flex: 1;
}

/* --- Showcase: full-width profile rows ----------------------------------- */

.upcsg-membershowcase {
    display: grid;
    gap: 1.5rem;
    margin-bottom: 2.5rem;
}

.upcsg-membercard--spotlight,
.upcsg-membercard--showcase {
    flex-direction: row;
    align-items: stretch;
}

/* The mirror. row-reverse rather than a reordered DOM, so the portrait stays before
   the text for a screen reader and for tab order however the row is drawn. */
.upcsg-membercard--flip { flex-direction: row-reverse; }

.upcsg-membercard--spotlight .upcsg-membercard__portrait,
.upcsg-membercard--showcase .upcsg-membercard__portrait {
    /* A fixed share of the card, so the portrait keeps its proportion instead of
       stretching to whatever height the bio happens to produce. */
    flex: 0 0 clamp(8rem, 26%, 14rem);
    aspect-ratio: auto;
}

.upcsg-membercard--spotlight .upcsg-membercard__portrait {
    flex-basis: clamp(10rem, 32%, 18rem);
}

.upcsg-membercard--spotlight .upcsg-membercard__body,
.upcsg-membercard--showcase .upcsg-membercard__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: clamp(1.25rem, 3vw, 2.25rem);
}

.upcsg-membercard--showcase .upcsg-membercard__name {
    font-size: clamp(1.35rem, 2.6vw, 1.8rem);
}

.upcsg-membercard--spotlight .upcsg-membercard__name {
    font-size: clamp(1.7rem, 3.6vw, 2.5rem);
}

.upcsg-membercard--spotlight .upcsg-membercard__quote,
.upcsg-membercard--showcase .upcsg-membercard__quote {
    -webkit-line-clamp: unset;
    line-clamp: unset;
    font-size: 1.02rem;
}

.upcsg-membercard--spotlight .upcsg-membercard__quote { font-size: 1.15rem; }

/* Four lines is roughly 400 characters at this measure. Today's bios are ~140 and
   never reach it; a long one clamps here and finishes in the dialog rather than
   stretching the row past its portrait. */
.upcsg-membercard__bio {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.8rem;
    font-size: 0.94rem;
    line-height: 1.65;
    color: var(--upcsg-periwinkle);
}

/* Stacks below the point where a side-by-side portrait leaves the text too narrow to
   read comfortably. The mirror is dropped with it: alternating left and right means
   nothing in a single column, and row-reverse would put the portrait under its own
   text for half the roster. */
@media (max-width: 46rem) {
    .upcsg-membercard--spotlight,
    .upcsg-membercard--showcase,
    .upcsg-membercard--flip {
        flex-direction: column;
    }

    .upcsg-membercard--spotlight .upcsg-membercard__portrait,
    .upcsg-membercard--showcase .upcsg-membercard__portrait {
        flex: none;
        aspect-ratio: 16 / 10;
    }
}

/* --- Row: compact strip for short committees ----------------------------- */

.upcsg-memberstrip {
    display: grid;
    gap: 1rem;
    margin-bottom: 2.5rem;
}

.upcsg-membercard--row {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    padding: 0.9rem 1.1rem;
}

.upcsg-membercard--row .upcsg-membercard__portrait {
    flex: 0 0 3.6rem;
    width: 3.6rem;
    aspect-ratio: 1;
    border-radius: 50%;
}

.upcsg-membercard--row .upcsg-membercard__body { padding: 0; }

.upcsg-membercard--row .upcsg-membercard__name { font-size: 1.1rem; }

.upcsg-membercard--row .upcsg-membercard__more { padding: 0.35rem 0 0; }

.upcsg-membercard__role {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-membercard__name {
    display: block;
    margin-top: 0.3rem;
    font-family: var(--upcsg-font-display);
    font-size: 1.25rem;
    line-height: 1.25;
    color: var(--upcsg-honeydew-white);
}

/* Two lines of the quote, then it stops. Free-text from the CMS varies wildly in
   length and unclamped it would make every card in the row a different height. */
.upcsg-membercard__quote {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 0.6rem;
    font-family: var(--upcsg-font-subheading);
    font-style: italic;
    font-size: 0.88rem;
    line-height: 1.45;
    color: var(--upcsg-periwinkle);
}

.upcsg-membercard__more {
    display: block;
    padding: 0.7rem 1.1rem 1.1rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--upcsg-cosmic-lavender);
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.upcsg-membercard:hover .upcsg-membercard__more,
.upcsg-membercard:focus-visible .upcsg-membercard__more {
    opacity: 1;
    transform: none;
}

/* Keyboard users never trigger :hover, so the affordance has to be visible whenever
   the card is focused â€” and on touch, where hover does not exist at all. */
@media (hover: none) {
    .upcsg-membercard__more { opacity: 1; transform: none; }
}

/* Committee divider: a rule with the name sitting on it. */
.upcsg-committee-rule {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    margin: 0 0 1.5rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-committee-rule::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, rgba(204, 174, 222, 0.4), transparent);
}

.upcsg-committee-rule__count {
    order: 1;
    padding: 0.1rem 0.55rem;
    border: var(--upcsg-hairline);
    border-radius: 999px;
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    color: var(--upcsg-periwinkle);
}

/* --- Maker's mark -------------------------------------------------------- */

/* Stacked under the email rather than given a row of its own, so it reads as a small
   signature on the contact block instead of a band across the footer. Kept in the same
   flex item as the email so it inherits that item's right-hand alignment. */
.upcsg-footer__contact {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.5rem;
}

.upcsg-madeby {
    display: inline-flex;

    /* Deliberately fainter than the footer text around it. A maker's mark should be
       findable rather than noticed; the hover state is what makes it legible. */
    color: var(--upcsg-periwinkle) !important;
    opacity: 0.25;
    transition: opacity 0.25s ease, color 0.25s ease;
}

.upcsg-madeby:hover,
.upcsg-madeby:focus-visible {
    /* Overrides the generic .upcsg-footer a:hover, which turns links gold â€” gold would
       fight the mark's own lilac dot. */
    color: var(--upcsg-honeydew-white) !important;
    opacity: 0.9;
}

.upcsg-madeby:focus-visible {
    outline: 2px solid var(--upcsg-liquid-chrome-gold);
    outline-offset: 4px;
    border-radius: 4px;
}

/* Height-driven; the viewBox is roughly 4:1 so the width follows. Sized below the
   footer's 0.85rem text so it sits under the email without rivalling it. */
.upcsg-madeby__mark {
    display: block;
    height: 16px;
    width: auto;
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-madeby { transition: none; }
}

/* --- Officer bands (About) ----------------------------------------------- *
   One band of page per officer, sides alternating. No card: the portrait is lit
   from behind by the nebula and the text sits on the page, so eleven officers
   read as eleven people rather than eleven identical gradient tiles.
 * ------------------------------------------------------------------------- */

.upcsg-officer {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: clamp(1.5rem, 5vw, 4rem);
    align-items: center;
    padding: clamp(2rem, 5vw, 3.25rem) 0;
    border-bottom: var(--upcsg-hairline);
}

.upcsg-officer:last-child { border-bottom: none; }

/* Reordering alone would leave the wide column on the same side, so the tracks
   swap with it. */
.upcsg-officer--flip { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }

.upcsg-officer--flip .upcsg-officer__plate { order: 2; }

.upcsg-officer__plate {
    position: relative;
    isolation: isolate;
}

.upcsg-officer__bloom {
    position: absolute;
    z-index: -1;
    inset: -12%;
    border-radius: 50%;
    background: radial-gradient(circle at 40% 35%, rgba(162, 83, 184, 0.55) 0%, transparent 68%);
    filter: blur(30px);
    pointer-events: none;
}

.upcsg-officer__portrait {
    aspect-ratio: 3 / 4;
    border-radius: var(--upcsg-radius);
    box-shadow: var(--upcsg-shadow-lg);
}

.upcsg-officer__role {
    margin: 0 0 0.5rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-officer__name {
    margin: 0;
    font-family: var(--upcsg-font-display);
    font-size: clamp(1.8rem, 4.5vw, 2.9rem);
    line-height: 1.05;
    color: var(--upcsg-honeydew-white);
}

.upcsg-officer__quote {
    margin: 1.1rem 0 0;
    padding-left: 1rem;
    border-left: 2px solid rgba(246, 200, 117, 0.35);
    font-family: var(--upcsg-font-subheading);
    font-size: 1.05rem;
    font-style: italic;
    line-height: 1.55;
    color: var(--upcsg-cosmic-lavender);
}

.upcsg-officer__quote::before { content: "\201C"; }
.upcsg-officer__quote::after { content: "\201D"; }

.upcsg-officer__bio {
    margin: 1.1rem 0 0;
    font-size: 0.95rem;
    line-height: 1.75;
    color: var(--upcsg-periwinkle);
}

.upcsg-officer__more { margin-top: 1.5rem; }

@media (max-width: 52rem) {
    .upcsg-officer,
    .upcsg-officer--flip {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.25rem;
    }

    /* On one column the portrait always leads: a picture below its own heading
       reads as belonging to the officer above it. */
    .upcsg-officer--flip .upcsg-officer__plate { order: 0; }

    .upcsg-officer__plate { max-width: 18rem; }
}

/* --- Member dialog ------------------------------------------------------- */

/* The dialog paper itself. MudBlazor's default is a flat plum rectangle, which is the
   one surface on the site that looked like a component library rather than the guild. */
/* The purple was doing too much: a 0.55 wash over the whole top plus a second bloom
   behind the portrait, which read as a purple card rather than as a night sky. The
   wash is halved and pushed into the corner, and a thin warm note comes in from the
   other side so the two brand colours share the surface instead of one flooding it. */
.upcsg-mdlg__paper {
    border-radius: 26px !important;
    border: var(--upcsg-hairline);
    overflow: hidden;

    background:
        radial-gradient(ellipse 90% 60% at 12% 0%, rgba(83, 37, 126, 0.28) 0%, transparent 62%),
        radial-gradient(ellipse 70% 50% at 95% 8%, rgba(226, 190, 122, 0.09) 0%, transparent 60%),
        linear-gradient(180deg, #171240 0%, #100C2B 100%) !important;

    box-shadow: var(--upcsg-shadow-lg) !important;
}

/* MudBlazor pads dialog content by default, which framed the portrait in a 24px
   border and made it read as a picture pasted into a box. */
.upcsg-mdlg__content {
    padding: 0 !important;
    overflow: hidden;
}

.upcsg-mdlg__actions {
    padding: 0.5rem 1.1rem 1rem !important;
    border-top: var(--upcsg-hairline);
}

.upcsg-mdlg {
    position: relative;
    outline: none;
}

/* Keyed on the officer index, so moving between profiles plays as a move rather than a
   silent content swap. */
.upcsg-mdlg__stage {
    animation: upcsg-mdlg-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes upcsg-mdlg-in {
    from { opacity: 0; transform: translateY(10px) scale(0.995); }
    to   { opacity: 1; transform: none; }
}

/* Masthead: the portrait at full frame beside the name, quote and all. A two-column
   grid rather than a flex row, so the text column can never be squeezed by a long
   name and the portrait keeps its ratio. */
.upcsg-mdlg__head {
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: clamp(8rem, 30%, 13rem) minmax(0, 1fr);
    gap: clamp(1.1rem, 3vw, 2rem);
    align-items: center;
    padding: clamp(1.75rem, 4vw, 2.5rem) clamp(1.5rem, 4vw, 2.5rem) clamp(1.5rem, 3.5vw, 2rem);
    border-bottom: 1px solid rgba(246, 200, 117, 0.22);
}

.upcsg-mdlg__bloom {
    position: absolute;
    z-index: -1;
    top: -30%;
    left: -8%;
    width: 45%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(162, 83, 184, 0.3) 0%, transparent 70%);
    filter: blur(34px);
    pointer-events: none;
}

.upcsg-mdlg__spark {
    position: absolute;
    z-index: 1;
    pointer-events: none;
}

.upcsg-mdlg__spark--a { top: 18%; right: 9%; }
.upcsg-mdlg__spark--a .upcsg-star { width: 0.9rem; height: 0.9rem; }

.upcsg-mdlg__spark--b { bottom: 22%; right: 22%; }
.upcsg-mdlg__spark--b .upcsg-star { width: 0.55rem; height: 0.55rem; }

/* The whole frame, at the crop the CMS asks portraits to be shot in, rather than a
   disc that cut everyone down to a head. */
.upcsg-mdlg__portrait {
    width: 100%;
    aspect-ratio: 3 / 4;
    border-radius: var(--upcsg-radius);
    border: 1px solid rgba(246, 200, 117, 0.28);
    box-shadow: var(--upcsg-shadow-md);
}

.upcsg-mdlg__close {
    position: absolute !important;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 4;
    color: var(--upcsg-text-muted) !important;
    background: rgba(6, 3, 24, 0.5) !important;
}

.upcsg-mdlg__title { min-width: 0; }

.upcsg-mdlg__role {
    margin: 0 0 0.35rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-mdlg__name {
    margin: 0;
    font-family: var(--upcsg-font-display);
    font-size: clamp(1.6rem, 4.5vw, 2.5rem);
    line-height: 1.06;
    color: var(--upcsg-honeydew-white);
}

.upcsg-mdlg__chip {
    display: inline-block;
    margin-top: 0.6rem;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    border: 1px solid rgba(204, 174, 222, 0.3);
    background: rgba(204, 174, 222, 0.08);
    font-family: var(--upcsg-font-heading);
    font-size: 0.66rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

/* Their own words, in the metal rather than the lavender. Gold is the accent the rest
   of the card spends on the year gutter and the link icons, so the quote reading in it
   ties the head to the body; lavender put it in the same key as the background wash. */
.upcsg-mdlg__quote {
    margin: 1rem 0 0;
    padding-left: 0.9rem;
    border-left: 2px solid rgba(246, 200, 117, 0.4);
    font-family: var(--upcsg-font-display);
    font-size: clamp(1rem, 2.2vw, 1.25rem);
    font-style: italic;
    line-height: 1.45;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-mdlg__quote::before { content: "\201C"; }
.upcsg-mdlg__quote::after { content: "\201D"; }

.upcsg-mdlg__body {
    display: grid;
    gap: clamp(1.25rem, 3vw, 1.75rem);
    padding: clamp(1.25rem, 3.5vw, 2rem) clamp(1.5rem, 4vw, 2.5rem) clamp(1.5rem, 4vw, 2rem);
    max-height: min(46vh, 30rem);
    overflow-y: auto;
}

.upcsg-mdlg__prose p {
    margin: 0 0 0.85rem;
    font-size: 0.95rem;
    line-height: 1.75;
    color: var(--upcsg-periwinkle);
}

.upcsg-mdlg__prose p:last-child { margin-bottom: 0; }

.upcsg-mdlg__prose--none {
    font-style: italic;
    opacity: 0.75;
    color: var(--upcsg-text-muted);
}

.upcsg-mdlg__panel {
    padding-top: clamp(1rem, 2.5vw, 1.35rem);
    border-top: var(--upcsg-hairline);
}

.upcsg-mdlg__panel-title {
    margin: 0 0 0.85rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

/* Year gutter: a fixed first column so the eye runs down the dates. */
.upcsg-mdlg__record {
    display: grid;
    gap: 0.55rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.upcsg-mdlg__record li {
    display: grid;
    grid-template-columns: 3.25rem minmax(0, 1fr);
    gap: 0.75rem;
    align-items: baseline;
}

.upcsg-mdlg__year {
    font-family: var(--upcsg-font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--upcsg-liquid-chrome-gold);
    font-variant-numeric: tabular-nums;
}

.upcsg-mdlg__deed {
    font-size: 0.92rem;
    line-height: 1.5;
    color: var(--upcsg-honeydew-white);
}

.upcsg-mdlg__links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.upcsg-mdlg__links a {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0.15rem 0.6rem;
    align-items: center;
    padding: 0.55rem 0.75rem;
    border: var(--upcsg-hairline);
    border-radius: 12px;
    background: rgba(246, 255, 233, 0.03);
    text-decoration: none;
    transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}

.upcsg-mdlg__links a:hover,
.upcsg-mdlg__links a:focus-visible {
    transform: translateY(-1px);
    border-color: rgba(246, 200, 117, 0.4);
    background: rgba(246, 200, 117, 0.08);
}

.upcsg-mdlg__links .mud-icon-root {
    grid-row: 1 / span 2;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-mdlg__linkkind {
    font-family: var(--upcsg-font-heading);
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

.upcsg-mdlg__linkvalue {
    font-size: 0.85rem;
    color: var(--upcsg-honeydew-white);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 40rem) {
    .upcsg-mdlg__head { grid-template-columns: minmax(0, 1fr); }

    /* The portrait keeps its ratio but stops eating the screen once it is the only
       thing in the column. */
    .upcsg-mdlg__portrait { max-width: 11rem; }
}

.upcsg-mdlg__nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 0.5rem;
}

/* Circular ghost arrows rather than text buttons carrying the neighbour's first name.
   The names made the footer read like breadcrumbs and pushed the counter off-centre;
   the name each arrow leads to is still announced, on aria-label. */
.upcsg-mdlg__arrow {
    border: var(--upcsg-hairline) !important;
    background: rgba(246, 255, 233, 0.04) !important;
    color: var(--upcsg-cosmic-lavender) !important;
    transition: background 0.25s ease, color 0.25s ease, transform 0.25s ease;
}

.upcsg-mdlg__arrow:hover {
    background: rgba(162, 83, 184, 0.22) !important;
    color: var(--upcsg-honeydew-white) !important;
    transform: scale(1.08);
}

/* Set as a fraction in the display face: "03 / 11" reads as a position in a series,
   where "3 / 11" read as a page number. */
.upcsg-mdlg__pos {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    font-family: var(--upcsg-font-display);
    letter-spacing: 0.06em;
}

.upcsg-mdlg__pos-now {
    font-size: 1.25rem;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-mdlg__pos-of {
    font-size: 0.85rem;
    color: var(--upcsg-periwinkle);
    opacity: 0.8;
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-mdlg__stage { animation: none; }
    .upcsg-mdlg__arrow { transition: none; }
}

/* --- Ways in (Contact) --------------------------------------------------- *
   Replaced a purple quote slab whose line restated the heading next to it. This
   is a list rather than a plate: no fixed aspect ratio to fill, so it ends where
   its content ends, and the gold marks the four routes without another gradient.
 * ------------------------------------------------------------------------- */

.upcsg-waysin {
    padding: clamp(1.25rem, 3vw, 1.75rem);
    border: var(--upcsg-hairline);
    border-radius: var(--upcsg-radius);
    background: rgba(246, 255, 233, 0.03);
}

.upcsg-waysin__title {
    margin: 0 0 1.1rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--upcsg-liquid-chrome-gold);
}

.upcsg-waysin__list {
    display: grid;
    gap: 1.1rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.upcsg-waysin__list li {
    padding-left: 1.1rem;
    border-left: 2px solid rgba(246, 200, 117, 0.3);
}

.upcsg-waysin__what {
    display: block;
    font-family: var(--upcsg-font-heading);
    font-weight: 600;
    font-size: 0.98rem;
    color: var(--upcsg-honeydew-white);
}

.upcsg-waysin__how {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--upcsg-periwinkle);
}

/* --- About: identity ----------------------------------------------------- *
   Claim, then evidence, then belief. The statement is centred and narrow so it
   reads as a single sentence rather than a column of body copy; the rail below
   is the only place on the site with real photography, so it gets the full
   width of the viewport; the creed closes the section in the guild's own words.
 * ------------------------------------------------------------------------- */

.upcsg-identity__statement {
    max-width: 44rem;
    margin: 0 auto;
    text-align: center;
}

.upcsg-identity__title {
    font-family: var(--upcsg-font-display);
    font-size: clamp(2.2rem, 6vw, 4rem);
    line-height: 1.04;
    margin: 0 0 1.25rem;
    color: var(--upcsg-honeydew-white);
}

.upcsg-identity__lede {
    margin-bottom: 0;
}

/* Breaks the page container so the photos run edge to edge. */
.upcsg-photorail {
    position: relative;
    margin: clamp(2.5rem, 6vw, 4rem) calc(50% - 50vw);
    overflow: hidden;

    /* Photos drift out of nothing rather than being cut off against an edge. The
       fade is a fixed width, not a percentage: at 10% of the viewport it grew with
       the window until 144px of photo sat ghosted at each end, which read as the
       rail failing to reach the edge rather than as a soft entry. */
    mask-image: linear-gradient(90deg, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
}

.upcsg-photorail__track {
    display: flex;
    width: max-content;
    animation: upcsg-marquee-scroll var(--rail-duration, 60s) linear infinite;
}

.upcsg-photorail:hover .upcsg-photorail__track {
    animation-play-state: paused;
}

.upcsg-photorail__run {
    display: flex;
    align-items: flex-start;
    gap: clamp(0.75rem, 2vw, 1.25rem);
    padding-right: clamp(0.75rem, 2vw, 1.25rem);
}

.upcsg-photorail__frame {
    margin: 0;
    flex: none;
}

/* Both dimensions are fixed rather than letting each photo size itself. Uniform
   frames read as a rail instead of a ragged strip, a portrait photo gets cropped
   rather than becoming a sliver, and the track's width does not change as images
   arrive - an auto width collapses to nothing until the file has loaded. */
.upcsg-photorail__frame img {
    display: block;
    width: clamp(14rem, 28vw, 22rem);
    height: clamp(11rem, 21vw, 16.5rem);
    object-fit: cover;
    background: rgba(246, 255, 233, 0.04);
    border-radius: var(--upcsg-radius);
    border: var(--upcsg-hairline);
    box-shadow: var(--upcsg-shadow-md);
}

.upcsg-photorail__frame figcaption {
    max-width: clamp(14rem, 28vw, 22rem);
    margin-top: 0.6rem;
    font-family: var(--upcsg-font-heading);
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    color: var(--upcsg-text-muted);
}

.upcsg-identity__creed {
    position: relative;
    isolation: isolate;
    max-width: 40rem;
    margin: 0 auto;
    padding-top: 1rem;
    text-align: center;
}

.upcsg-identity__burst {
    position: absolute;
    z-index: -1;
    top: 50%;
    left: 50%;
    width: clamp(16rem, 34vw, 26rem);
    transform: translate(-50%, -50%);
    opacity: 0.14;
    pointer-events: none;
}

.upcsg-identity__quote {
    margin: 0;
    font-family: var(--upcsg-font-display);
    font-size: clamp(1.35rem, 3.2vw, 2.1rem);
    line-height: 1.35;
    color: var(--upcsg-honeydew-white);
}

/* Quotation marks belong to the sentence, not to a decorative slab beside it. */
.upcsg-identity__quote::before { content: "\201C"; }
.upcsg-identity__quote::after { content: "\201D"; }

.upcsg-identity__source {
    margin: 1.1rem 0 0;
    font-family: var(--upcsg-font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--upcsg-text-muted);
}

/* A stopped marquee hides everything past the first screenful, so when motion is
   off the rail becomes something you can scroll through instead. */
@media (prefers-reduced-motion: reduce) {
    .upcsg-photorail {
        overflow-x: auto;
        mask-image: none;
        -webkit-mask-image: none;
    }

    .upcsg-photorail__track { animation: none; }

    .upcsg-photorail__run:nth-child(2) { display: none; }
}

.upcsg-statrow--spread {
    justify-content: space-around;
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

/* Hero drift: --scroll-depth is published by motion.js, so the parallax is described
   here rather than by a script writing inline styles every frame. */
.upcsg-hero__inner {
    transform: translateY(calc(var(--scroll-depth, 0) * 42px));
    opacity: calc(1 - var(--scroll-depth, 0) * 0.85);
}

@media (prefers-reduced-motion: reduce) {
    .upcsg-hero__inner { transform: none; opacity: 1; }
}
