/* =================================================================
   Identity components
   =================================================================

   Everything built between 5.0.0 and 6.3.0 shipped markup with class
   names and no styling: credentials, sessions, two-factor, visibility,
   data requests, the Passport page and the public verification page.
   The result rendered as unstyled flowing text, which is why the
   settings screens looked nothing like the design.

   A separate file rather than more appended blocks in redesign.css.
   That file is 13,300 lines organised by release chronology, with
   .profile-shell declared across 166 rules and .pf-card carrying 96
   cascade conflicts — appending to it is the habit that produced those
   numbers. These are new class names nothing else declares, so a new
   file costs one extra source entry and keeps them findable.

   Everything below uses design tokens with literal fallbacks, so it
   degrades rather than disappearing if a token is renamed.
   ================================================================= */

/* ---------- Shared section shell ------------------------------- */

.account-section {
    background: var(--color-white, #fff);
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .75rem;
    padding: var(--space-6, 1.5rem);
    margin-bottom: var(--space-6, 1.5rem);
}

.account-section > h2 {
    margin-top: 0;
    margin-bottom: .35rem;
    font-size: 1.25rem;
}

.account-section .description,
.account-section__intro {
    color: var(--color-neutral, #687280);
    font-size: .9375rem;
    margin-top: 0;
    max-width: 62ch;
}

.account-subsection {
    padding-top: var(--space-5, 1.25rem);
    margin-top: var(--space-5, 1.25rem);
    border-top: 1px solid var(--color-border, #E5E7EB);
}

.account-subsection h3 {
    margin: 0 0 .35rem;
    font-size: 1rem;
}

/* Forms inside a settings panel: label above field, comfortable rhythm. */
.account-section form label {
    display: block;
    font-weight: 600;
    font-size: .875rem;
    margin-bottom: .3rem;
}

.account-section form input[type="text"],
.account-section form input[type="email"],
.account-section form input[type="url"],
.account-section form input[type="password"] {
    width: 100%;
    max-width: 26rem;
    padding: .6rem .75rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
    margin-bottom: .5rem;
}

.account-section form button {
    margin-top: .5rem;
}

/* ---------- Credentials ---------------------------------------- */

.credential-list {
    list-style: none;
    margin: 0 0 var(--space-4, 1rem);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.credential-list__item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .5rem .75rem;
    padding: .8rem 1rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-left: 3px solid var(--color-positive, #16803C);
    border-radius: .5rem;
    background: var(--color-surface, #F7F7FD);
}

.credential-list__item strong {
    font-size: .9375rem;
}

.credential-list__date {
    color: var(--color-neutral, #687280);
    font-size: .8125rem;
}

.credential-list__item a {
    margin-left: auto;
    font-size: .8125rem;
}

/* ---------- Sessions ------------------------------------------- */

.session-list {
    list-style: none;
    margin: 0 0 var(--space-4, 1rem);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.session-list__item {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .8rem 1rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
}

.session-list__item.is-current {
    border-color: var(--color-primary, #6D5EF5);
    background: var(--color-surface, #F7F7FD);
}

.session-list__device {
    font-weight: 600;
    font-size: .9375rem;
}

.session-list__badge {
    display: inline-block;
    margin-left: .4rem;
    padding: .1rem .5rem;
    border-radius: 999px;
    background: var(--color-primary, #6D5EF5);
    color: #fff;
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
}

.session-list__meta {
    color: var(--color-neutral, #687280);
    font-size: .8125rem;
}

/* ---------- Privacy and visibility ------------------------------ */

.visibility-list {
    list-style: none;
    margin: var(--space-4, 1rem) 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.visibility-list__row {
    display: grid;
    grid-template-columns: 1fr minmax(9rem, 12rem);
    align-items: center;
    gap: 1rem;
    padding: .6rem .8rem;
    border-radius: .5rem;
}

.visibility-list__row:nth-child(odd) {
    background: var(--color-surface, #F7F7FD);
}

.visibility-list__label {
    font-weight: 600;
    font-size: .9375rem;
    margin: 0;
}

.visibility-list__select {
    width: 100%;
    padding: .45rem .6rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
    background: var(--color-white, #fff);
}

@media (max-width: 560px) {
    .visibility-list__row {
        grid-template-columns: 1fr;
        gap: .35rem;
    }
}

/* ---------- Data requests --------------------------------------- */

.privacy-requests {
    list-style: none;
    margin: .75rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.privacy-requests__item {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: .75rem;
    align-items: baseline;
    padding: .55rem .8rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
    font-size: .875rem;
}

.privacy-requests__type {
    font-weight: 600;
}

.privacy-requests__status,
.privacy-requests__date {
    color: var(--color-neutral, #687280);
}

/* ---------- Two-factor ------------------------------------------ */

/* The setup key is read character by character off the screen and
   typed into a phone, so it is monospaced, spaced out, and large
   enough that 8 and B are distinguishable. */
.totp-secret code {
    display: inline-block;
    padding: .75rem 1rem;
    border: 1px dashed var(--color-primary, #6D5EF5);
    border-radius: .5rem;
    background: var(--color-surface, #F7F7FD);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.125rem;
    letter-spacing: .12em;
    user-select: all;
}

.recovery-codes {
    list-style: none;
    margin: .75rem 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    gap: .4rem;
}

.recovery-codes code {
    display: block;
    padding: .5rem .6rem;
    border-radius: .4rem;
    background: var(--color-white, #fff);
    border: 1px solid var(--color-border, #E5E7EB);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .9375rem;
    text-align: center;
    user-select: all;
}
.is-jumped { box-shadow: 0 0 0 3px #E9E8FC, 0 0 0 5px var(--color-primary, #5D4FE6); transition: box-shadow .3s; }

/* ---------- Public verification page ---------------------------- */

.verify-page {
    max-width: 40rem;
    margin-inline: auto;
    padding: var(--space-8, 2rem) var(--space-4, 1rem);
}

.verify-page__status {
    padding: .7rem 1rem;
    border-radius: .5rem;
    font-weight: 600;
}

.verify-page__status--valid {
    background: var(--color-positive-soft, #DCFCE7);
    color: var(--color-positive, #16803C);
}

.verify-page__status--revoked {
    background: var(--color-danger-soft, #FEF2F2);
    color: var(--color-danger, #DC2626);
}

.verify-page__status--expired {
    background: var(--color-warning-soft, #FEF3C7);
    color: var(--color-warning, #B45309);
}

.verify-page__facts {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: .5rem 1.25rem;
    margin: var(--space-5, 1.25rem) 0;
}

.verify-page__facts dt {
    color: var(--color-neutral, #687280);
}

.verify-page__facts dd {
    margin: 0;
    font-weight: 600;
}

.verify-page__evidence {
    margin: 0 0 var(--space-4, 1rem);
    padding-left: 1.1rem;
}

.verify-page__code {
    color: var(--color-neutral, #687280);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- Suspended account ----------------------------------- */

.account-suspended {
    max-width: 34rem;
    margin-inline: auto;
    padding: var(--space-10, 2.5rem) var(--space-4, 1rem);
    text-align: center;
}

.account-suspended__lede {
    color: var(--color-neutral, #687280);
}

.account-suspended__reason {
    text-align: left;
    padding: 1rem 1.25rem;
    border-radius: .5rem;
    background: var(--color-danger-soft, #FEF2F2);
    border-left: 3px solid var(--color-danger, #DC2626);
    margin: var(--space-5, 1.25rem) 0;
}

.account-suspended__reason p {
    margin: .35rem 0 0;
}

/* ---------- Privacy and preferences tabs ------------------------ */

.pref-tabs__nav {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    border-bottom: 1px solid var(--color-border, #E5E7EB);
    margin-bottom: .75rem;
}

.pref-tabs__tab {
    padding: .6rem .9rem;
    border-bottom: 2px solid transparent;
    color: var(--color-neutral, #687280);
    text-decoration: none;
    font-weight: 600;
    font-size: .9375rem;
    white-space: nowrap;
}

.pref-tabs__tab:hover,
.pref-tabs__tab:focus-visible {
    color: var(--color-primary, #6D5EF5);
}

.pref-tabs__tab.is-current {
    color: var(--color-primary, #6D5EF5);
    border-bottom-color: var(--color-primary, #6D5EF5);
}

.pref-tabs__blurb {
    color: var(--color-neutral, #687280);
    font-size: .9375rem;
    margin: 0 0 var(--space-4, 1rem);
}

/* The panel already contains .account-section blocks, which carry
   their own border and padding — a second frame around them would be
   a box inside a box. */
.pref-tabs__panel > .account-section {
    border: none;
    padding: 0;
    margin-bottom: var(--space-6, 1.5rem);
}

@media (max-width: 560px) {
    .pref-tabs__nav {
        overflow-x: auto;
        flex-wrap: nowrap;
    }
}

/* Below 1100px the aside stops being a column and becomes a compact
   summary above the form. Keeping it beside a form at tablet width
   squeezes both into unusable widths — but stacking it unchanged is
   worse still: ten full-width rows push the form itself a screen and a
   half down, so the panel meant to help you finish is the thing
   stopping you from starting.

   So on narrow screens it becomes a horizontal strip: the percentage,
   then the sections as small chips that scroll sideways. Same
   information, one thumb-width of vertical space. */
@media (max-width: 1100px) {


    .wizard-aside {
        order: -1;
        gap: .75rem;
    }

    .wizard-aside__panel {
        padding: .9rem 1rem;
    }

    .wizard-aside__overall {
        margin-bottom: .6rem;
    }

    .wizard-aside__percent {
        font-size: 1.5rem;
    }

    /* Rows become chips on a single scrolling line. */
    .wizard-aside__list {
        flex-direction: row;
        gap: .4rem;
        overflow-x: auto;
        padding-bottom: .35rem;
        scroll-snap-type: x proximity;
        -webkit-overflow-scrolling: touch;
    }

    .wizard-aside__row {
        flex: 0 0 auto;
        min-width: 8.5rem;
        padding: .5rem .65rem;
        border: 1px solid var(--color-border, #E5E7EB);
        border-radius: .5rem;
        scroll-snap-align: start;
    }

    .wizard-aside__row.is-current {
        border-color: var(--color-primary, #6D5EF5);
        background: var(--color-surface, #F7F7FD);
    }

    .wizard-aside__jump {
        flex-direction: column;
        align-items: flex-start;
        gap: .1rem;
        padding-bottom: .35rem;
    }

    .wizard-aside__row-label {
        font-size: .75rem;
        line-height: 1.2;
    }

    .wizard-aside__row-value {
        font-size: .6875rem;
        font-weight: 700;
    }

    .wizard-aside__track {
        height: 4px;
    }

    /* Tips are useful and not urgent. On a small screen they sit
       behind a tap rather than between the member and the form. */
    .wizard-aside__panel--tips {
        display: none;
    }
}

/* Phones: the strip stays, the panel loses its card framing so it
   reads as part of the page rather than a box balanced on top of it. */
@media (max-width: 560px) {
    .wizard-aside__panel {
        border-left: 0;
        border-right: 0;
        border-radius: 0;
        margin-inline: calc(var(--space-4, 1rem) * -1);
        padding-inline: var(--space-4, 1rem);
    }

    .wizard-aside__overall {
        align-items: center;
    }
}

.wizard-aside {
    display: flex;
    flex-direction: column;
    gap: var(--space-4, 1rem);
    position: sticky;
    top: calc(var(--jdev-header-h, 64px) + 1rem);
}

@media (max-width: 1100px) {
    .wizard-aside {
        position: static;
    }
}

.wizard-aside__panel {
    background: var(--color-white, #fff);
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .75rem;
    padding: var(--space-5, 1.25rem);
}

.wizard-aside__title {
    margin: 0 0 .75rem;
    font-size: .8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--color-neutral, #687280);
}

.wizard-aside__overall {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    margin: 0 0 1rem;
}

.wizard-aside__percent {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-primary, #6D5EF5);
}

.wizard-aside__overall-label {
    font-size: .8125rem;
    color: var(--color-neutral, #687280);
}

.wizard-aside__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

.wizard-aside__jump {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .5rem;
    width: 100%;
    padding: 0 0 .25rem;
    background: none;
    border: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    text-align: left;
}

.wizard-aside__row-label {
    font-size: .875rem;
}

.wizard-aside__row.is-current .wizard-aside__row-label {
    font-weight: 700;
    color: var(--color-primary, #6D5EF5);
}

.wizard-aside__row-value {
    font-size: .8125rem;
    font-variant-numeric: tabular-nums;
    color: var(--color-neutral, #687280);
}

.wizard-aside__track {
    display: block;
    height: 6px;
    border-radius: 999px;
    background: var(--color-border, #E5E7EB);
    overflow: hidden;
}

.wizard-aside__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--color-primary, #6D5EF5);
    transition: width .3s ease;
}

/* Finished sections read green, so the list can be scanned for gaps
   without reading a single number. */
.wizard-aside__fill.is-complete {
    background: var(--color-positive, #16803C);
}

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

.wizard-aside__panel--tips {
    background: var(--color-surface, #F7F7FD);
    border-color: transparent;
}

.wizard-aside__tips {
    margin: 0;
    padding-left: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    font-size: .875rem;
    line-height: 1.45;
}

.wizard-aside__tips li::marker {
    color: var(--color-primary, #6D5EF5);
}

/* ---------- Settings screens on mobile -------------------------- */

/* The settings sidebar collapses to a scrolling row above 900px in
   the earlier block. Below that the panel needs the same edge-to-edge
   treatment as the wizard aside, or every screen reads as a narrow
   card floating in a margin. */
@media (max-width: 560px) {
    .settings-layout__panel {
        border-left: 0;
        border-right: 0;
        border-radius: 0;
        margin-inline: calc(var(--space-4, 1rem) * -1);
        padding: var(--space-5, 1.25rem) var(--space-4, 1rem);
    }

    .settings-nav__item {
        padding: .85rem 1rem;
    }

    .settings-nav__blurb {
        font-size: .8125rem;
    }

    .account-section {
        padding: var(--space-4, 1rem);
    }

    .account-section form input[type="text"],
    .account-section form input[type="email"],
    .account-section form input[type="url"],
    .account-section form input[type="password"] {
        max-width: none;
    }

    /* Full-width targets: a 44px-tall button that spans the column is
       reachable with a thumb without aiming. */
    .account-section form button,
    .account-section .btn {
        width: 100%;
        min-height: 44px;
    }

    .credential-list__item,
    .privacy-requests__item {
        grid-template-columns: 1fr;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: .25rem;
    }

    .credential-list__item a {
        margin-left: 0;
    }

    .recovery-codes {
        grid-template-columns: repeat(2, 1fr);
    }

    .totp-secret code {
        font-size: 1rem;
        letter-spacing: .08em;
        word-break: break-all;
    }
}

/* The wizard's own step nav: a scrolling strip rather than a wrapped
   block that pushes the form down. */
@media (max-width: 900px) {
    .profile-wizard__steps {
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: .35rem;
        padding-bottom: .4rem;
        -webkit-overflow-scrolling: touch;
    }

    .profile-wizard__step {
        flex: 0 0 auto;
        white-space: nowrap;
    }
}

/* Save and Save & continue side by side on a phone, with the primary
   action on the right where the thumb already is. */
@media (max-width: 560px) {
    .wizard-saved {
        display: block;
        margin: 0 0 .5rem;
        text-align: center;
    }
}


/* ---------- Profile builder ------------------------------------- */

/* Main column plus a rail. The rail is fixed-width so the form column
   takes the remainder — the reverse (both fractional) is what made the
   form squeeze to an unusable width on a laptop. */
.pb-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: var(--space-6, 1.5rem);
    align-items: start;
}

.pb-layout__main {
    min-width: 0;
}

@media (max-width: 1199px) {
    .pb-layout {
        grid-template-columns: 1fr;
    }
}

.pb__header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: var(--space-4, 1rem);
}

.pb__title { margin: 0 0 .25rem; }

.pb__lede {
    margin: 0;
    color: var(--color-neutral, #687280);
    max-width: 56ch;
}

.pb__progress {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: .75rem;
    margin-bottom: var(--space-5, 1.25rem);
    font-size: .8125rem;
    color: var(--color-neutral, #687280);
}

.pb__progress-track {
    height: 6px;
    border-radius: 999px;
    background: var(--color-border, #E5E7EB);
    overflow: hidden;
}

.pb__progress-fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--color-primary, #6D5EF5);
}

.pb__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

/* ---- A group card ---- */

.pb-card {
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .75rem;
    background: var(--color-white, #fff);
    overflow: hidden;
}

.pb-card.is-open {
    border-color: var(--color-primary, #6D5EF5);
    box-shadow: 0 0 0 1px var(--color-primary, #6D5EF5);
}

.pb-card__head {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    align-items: start;
    gap: 1rem;
    padding: 1.15rem 1.25rem;
}

.pb-card__index {
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--color-border, #E5E7EB);
    font-size: .8125rem;
    font-weight: 700;
}

.pb-card.is-open .pb-card__index,
.pb-card--complete .pb-card__index {
    background: var(--color-primary, #6D5EF5);
    color: #fff;
}

.pb-card--complete .pb-card__index {
    background: var(--color-positive, #16803C);
}

.pb-card__icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: .6rem;
    background: var(--color-surface, #F7F7FD);
    color: var(--color-primary, #6D5EF5);
}

.pb-card__heading { min-width: 0; }

.pb-card__title { margin: 0 0 .15rem; font-size: 1.0625rem; }

.pb-card__blurb {
    margin: 0 0 .5rem;
    color: var(--color-neutral, #687280);
    font-size: .875rem;
}

.pb-card__sections {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: .3rem 1rem;
    font-size: .8125rem;
    color: var(--color-neutral, #687280);
}

.pb-card__section.is-done { color: var(--color-positive, #16803C); }

.pb-card__actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .5rem;
    white-space: nowrap;
}

.pb-card__status {
    font-size: .75rem;
    font-weight: 700;
    padding: .25rem .6rem;
    border-radius: 999px;
    background: var(--color-border, #E5E7EB);
    color: var(--color-neutral, #687280);
}

.pb-card--complete .pb-card__status {
    background: var(--color-positive-soft, #DCFCE7);
    color: var(--color-positive, #16803C);
}

.pb-card--started .pb-card__status {
    background: var(--color-surface, #F7F7FD);
    color: var(--color-primary, #6D5EF5);
}

/* ---- The open group's sections, side by side ---- */

/* auto-fit with a floor: three sections become three columns on a wide
   screen, two on a laptop, one on a phone — without a breakpoint per
   group, since groups hold different numbers of sections. */
.pb-card__panels {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--space-4, 1rem);
    padding: 0 1.25rem 1.25rem;
    border-top: 1px solid var(--color-border, #E5E7EB);
    padding-top: 1.25rem;
}

.pb-card__panels--single {
    grid-template-columns: 1fr;
}

/* The section parts were written as full-width wizard steps. Inside a
   column they must drop their own framing, or every column is a card
   inside a card inside a card. */
.pb-card__panels [data-wizard-panel] {
    display: block;
    min-width: 0;
    background: var(--color-surface, #F7F7FD);
    border-radius: .6rem;
    padding: 1rem;
}

.pb-card__panels [data-wizard-panel] > h2,
.pb-card__panels [data-wizard-panel] > h3 {
    margin-top: 0;
    font-size: 1rem;
}

.pb-card__panels input[type="text"],
.pb-card__panels input[type="email"],
.pb-card__panels input[type="url"],
.pb-card__panels input[type="tel"],
.pb-card__panels input[type="number"],
.pb-card__panels select,
.pb-card__panels textarea {
    width: 100%;
    max-width: 100%;
}

/* Buttons wrap instead of overflowing the column — this is what pushed
   Save & continue outside its card. */
.pb-card__panels .profile-wizard__actions,
.pb-card__panels .form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: center;
}

.pb-card__panels .btn {
    max-width: 100%;
}

/* ---- Review & publish ---- */

.pb-review {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-4, 1rem);
}

.pb-review__title {
    margin: 0 0 .6rem;
    font-size: .9375rem;
}

.pb-review__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}

.pb-review__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    gap: .75rem;
    padding: .6rem .8rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
    font-size: .875rem;
}

.pb-review__row-count { color: var(--color-neutral, #687280); font-size: .8125rem; }
.pb-review__row-state.is-ok { color: var(--color-positive, #16803C); font-weight: 700; }
.pb-review__row-state.is-partial { color: var(--color-accent-text, #A76902); font-weight: 700; }

.pb-review__preview {
    background: var(--color-surface, #F7F7FD);
    border-radius: .6rem;
    padding: 1rem;
}

.pb-review__note {
    font-size: .875rem;
    color: var(--color-neutral, #687280);
}

/* ---- Small screens ---- */

@media (max-width: 700px) {
    .pb-card__head {
        grid-template-columns: auto minmax(0, 1fr);
        gap: .5rem .75rem;
        padding: 1rem;
    }

    .pb-card__icon { display: none; }

    .pb-card__heading { grid-column: 2; }

    .pb-card__actions {
        grid-column: 1 / -1;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        width: 100%;
    }

    .pb-card__actions .btn {
        min-height: 44px;
        padding-inline: 1.5rem;
    }

    .pb-card__panels {
        padding: 1rem;
        gap: .75rem;
    }

    .pb__progress { grid-template-columns: 1fr; gap: .35rem; }

    .pb__header .btn { width: 100%; }
}

/* ---------- Repeatable collections ------------------------------ */

.coll {
    margin-bottom: var(--space-4, 1rem);
}

.coll__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .5rem;
}

.coll__title { margin: 0; font-size: .9375rem; }

.coll__count { font-size: .75rem; color: var(--color-neutral, #687280); }

.coll__empty {
    margin: 0 0 .5rem;
    font-size: .875rem;
    color: var(--color-neutral, #687280);
}

.coll__list {
    list-style: none;
    margin: 0 0 .6rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}

.coll__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: .4rem .6rem;
    padding: .65rem .8rem;
    background: var(--color-white, #fff);
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .5rem;
}

/* A record with a validation problem is flagged where the member can
   act on it, not only summarised on a review screen they may not open. */
.coll__item.has-problem {
    border-left: 3px solid var(--color-accent, #F59E0B);
}

.coll__item-main { min-width: 0; }

.coll__item-title {
    display: block;
    font-size: .875rem;
    overflow-wrap: anywhere;
}

.coll__item-sub {
    font-size: .8125rem;
    color: var(--color-neutral, #687280);
    overflow-wrap: anywhere;
}

.coll__problem {
    margin: .25rem 0 0;
    font-size: .75rem;
    color: var(--color-warning, #B45309);
}

.coll__item-actions {
    display: flex;
    align-items: flex-start;
    gap: .15rem;
}

.coll__inline { display: inline; }

.coll__icon-btn {
    width: 1.9rem;
    height: 1.9rem;
    display: grid;
    place-items: center;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .35rem;
    background: var(--color-white, #fff);
    cursor: pointer;
    font-size: .8125rem;
    line-height: 1;
}

.coll__icon-btn[disabled] { opacity: .35; cursor: default; }

.coll__icon-btn--danger { color: var(--color-danger, #DC2626); }

.coll__edit,
.coll__add { grid-column: 1 / -1; }

.coll__edit > summary {
    cursor: pointer;
    font-size: .8125rem;
    color: var(--color-primary, #6D5EF5);
}

.coll__add > summary {
    cursor: pointer;
    display: inline-block;
    list-style: none;
}

.coll__add > summary::-webkit-details-marker { display: none; }

.coll__form {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    margin-top: .6rem;
    padding: .8rem;
    background: var(--color-surface, #F7F7FD);
    border-radius: .5rem;
}

.coll__form label {
    font-size: .75rem;
    font-weight: 600;
    margin: 0;
}

.coll__form input,
.coll__form textarea {
    width: 100%;
    padding: .45rem .6rem;
    border: 1px solid var(--color-border, #E5E7EB);
    border-radius: .4rem;
    font-size: .875rem;
}

.coll__form button { align-self: flex-start; margin-top: .4rem; }

/* Stacked cards on a phone, per specification section 10. Actions get
   a full-height touch target rather than 1.9rem icons. */
@media (max-width: 560px) {
    .coll__item { grid-template-columns: 1fr; }

    .coll__item-actions { justify-content: flex-end; }

    .coll__icon-btn { width: 2.6rem; height: 2.6rem; }

    .coll__form button { align-self: stretch; min-height: 44px; }
}

/* Needs attention: amber, distinct from both complete and untouched. */
.pb-card--attention {
    border-color: var(--color-accent, #F59E0B);
}

.pb-card--attention .pb-card__index {
    background: var(--color-accent, #F59E0B);
    color: #fff;
}

.pb-card--attention .pb-card__status {
    background: var(--color-warning-soft, #FEF3C7);
    color: var(--color-warning, #B45309);
}

/* ===============================================================
   PEOPLE YOU MAY KNOW — card carousel
   ===============================================================
   The suggestion list was horizontal rows (avatar, text, button in a
   line). The wireframe specifies vertical cards in a scrollable row:
   avatar over name over headline over mutuals, with a full-width
   Connect and a dismiss in the corner.

   NOTE ON SPECIFICITY: legacy-overrides.css also styles .pymk__list
   and .pymk__item and is bundled AFTER this file, so these rules do
   not win on order. Each is prefixed with .pymk so it carries higher
   specificity than the bare class there. Keep the prefix.
   =============================================================== */
.pymk .pymk__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.pymk .pymk__title {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

.pymk .pymk__viewall {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-shrink: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--color-secondary-text);
}

/* ---- The row of cards ----
   A scroller rather than a wrapping grid: the wireframe shows four
   across with a next-arrow, and on a narrow screen a horizontal swipe
   keeps the section one row tall instead of growing to four. */
.pymk .pymk__list {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(210px, 1fr);
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-2);
  scrollbar-width: none;
}

.pymk .pymk__list::-webkit-scrollbar { display: none; }

/* Containment applies at EVERY width.
   These rules were written inside a max-width query, so the desktop
   sidebar — where the column is narrowest — never got them, and a long
   role like "Functional Consultant · Finance" ran straight out of its
   card. A card must never be widened by its own text. */
.pymk .pymk__item {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-1);
  min-width: 0;
  padding: var(--space-5) var(--space-4) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  scroll-snap-align: start;
}

.pymk .pymk__avatar { display: block; margin-bottom: var(--space-2); }

.pymk .pymk__avatar img {
  width: 72px;
  height: 72px;
  border-radius: var(--radius-full);
}

.pymk .pymk__body {
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
  width: 100%;
}

.pymk .pymk__name {
  max-width: 100%;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  overflow-wrap: anywhere;
}

.pymk .pymk__headline,
.pymk .pymk__reason {
  max-width: 100%;
  /* Two lines then truncate: a role is context, and letting it run to
     four lines pushes the Connect button out of sight in a card row
     whose height is set by its tallest member. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

/* ---- Actions ---- */
.pymk .pymk__action {
  width: 100%;
  /* auto, not a fixed gap: the body above grows to fill the card, so
     this pushes the button to the bottom and every Connect in the row
     lands on the same line whether or not that person has a headline. */
  margin-top: auto;
  padding-top: var(--space-3);
}

.pymk .pymk__action .btn { width: 100%; }

/* ---- Dismiss ---- */
.pymk .pymk__dismiss {
  position: absolute;
  top: var(--space-2);
  inset-inline-end: var(--space-2);
  margin: 0;
}

.pymk .pymk__dismiss-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Comfortable target without a visible 32px button crowding the
     card's corner. */
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
}

.pymk .pymk__dismiss-btn:hover,
.pymk .pymk__dismiss-btn:focus-visible { color: var(--color-ink); }

@media (max-width: 767px) {
  .pymk .pymk__list {
    grid-auto-columns: minmax(160px, 76%);
    gap: var(--space-3);
  }

  .pymk .pymk__avatar img { width: 60px; height: 60px; }
}

/* ===============================================================
   NETWORK PAGE — tabs, list header, connection rows
   ===============================================================
   NOTE ON SPECIFICITY: legacy-overrides.css also styles .network-row
   and .network-tab and is bundled AFTER this file, so these rules are
   prefixed with .network-page to outrank it (0,2,0 against 0,1,0).
   Keep the prefix.
   =============================================================== */
.network-page .network-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.network-page .network-tab__icon {
  display: inline-flex;
  flex-shrink: 0;
  /* Dimmer than the label until the tab is current, so five icons do
     not compete with the one that matters. */
  color: var(--color-text-muted);
}

.network-page .network-tab.is-active .network-tab__icon { color: var(--color-primary); }

/* ---- List header ---- */
.network-page .network-list__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: var(--space-6) 0 var(--space-3);
}

.network-page .network-list__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

.network-page .network-list__title .icon { color: var(--color-text-muted); }

/* ---- Row ---- */
.network-page .network-row__nameline {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* "You" — a label, not a control, so it is a quiet chip rather than a
   button. */
.network-page .network-row__you {
  padding: 1px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-code-inline-bg);
  color: var(--color-secondary-text);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}

.network-page .network-row__where {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 2px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

.network-page .network-row__sep { color: var(--color-border); }

/* ---- Expertise ---- */
.network-page .network-row__expertise { min-width: 0; }

.network-page .network-row__expertise-label {
  margin: 0 0 var(--space-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--color-text-muted);
}

.network-page .network-row__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.network-page .network-row__tag {
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  font-size: var(--fs-xs);
  color: var(--color-ink-soft);
  white-space: nowrap;
}

.network-page .network-row__tag--more {
  background: var(--color-code-inline-bg);
  border-color: transparent;
  color: var(--color-secondary-text);
  font-weight: var(--fw-semibold);
}

/* The row becomes avatar | body | expertise | actions on wide screens,
   and stacks below that — the expertise column is the first thing to
   go, since it is context rather than identity or action. */
@media (min-width: 1024px) {
  .network-page .network-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1.4fr) minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-4);
  }
}

@media (max-width: 1023px) {
  .network-page .network-row__expertise { display: none; }
}

/* ===============================================================
   NETWORK PAGE — two-column layout
   ===============================================================
   Lists on the left, Discover on the right.

   Discover used to sit above the lists, inside the tab flow, so every
   tab switch pushed the rows the member came for further down. It is
   not part of any of the five lists, so it does not belong in that
   column at all.
   =============================================================== */
.network-page .network-layout {
  display: grid;
  /* minmax(0, …), not 1fr: a long name or a wide row would otherwise
     widen the column past the page. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}

@media (min-width: 1024px) {
  .network-page .network-layout {
    grid-template-columns: minmax(0, 1fr) 320px;
  }
}

.network-page .network-layout__main,
.network-page .network-layout__aside {
  min-width: 0;
}

/* Below the desktop breakpoint the sidebar falls BELOW the lists, not
   above them — the same reasoning as moving it out of the tab flow. */
@media (max-width: 1023px) {
  .network-page .network-layout__aside { order: 2; }
}

/* The panel is focusable so the tab script can move focus into it, but
   it should not draw a focus ring when it does — the ring belongs on
   things the member is operating, not on a region they were moved to. */
.network-page .network-panel:focus { outline: none; }

/* In the narrower sidebar the suggestion cards stack rather than
   scrolling sideways: a horizontal scroller inside a 320px column
   shows barely one card and hides the rest behind a gesture. */
@media (min-width: 1024px) {
  /* Two across, like the homepage rail — not one per row.
     A single column made each card the full width of the sidebar,
     which turned a compact discovery block into a tall list and pushed
     everything below it off the screen. */
  .network-page .network-layout__aside .pymk__list {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
    overflow-x: visible;
  }

  /* NOT sticky, and no inner scroll.
     Making it sticky meant capping it to the viewport and giving it
     overflow-y: auto — which put a second scrollbar on the page and,
     worse, hid everything below the fold INSIDE it. The Recent activity
     panel sits under Network insights, so it fell into that hidden
     region and looked absent on desktop while showing fine on mobile,
     where the column is not capped.
     The aside now flows at its natural height: every panel is on the
     page and reached by scrolling the page itself. */
  .network-page .network-layout__aside {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

/* ===============================================================
   NETWORK PAGE — summary bar, glance, activity, grow
   =============================================================== */

/* ---- Four-stat summary ---- */
.network-page .network-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-2);
  margin: var(--space-5) 0 var(--space-5);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  list-style: none;
}

.network-page .network-summary__item { min-width: 0; }

.network-page .network-summary__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  color: var(--color-ink);
}

.network-page .network-summary__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  color: var(--stat-accent, var(--color-primary));
  background: var(--stat-tint, var(--color-bg-alt));
}

.network-page .network-summary__icon--indigo { --stat-accent: var(--color-primary); --stat-tint: color-mix(in srgb, var(--color-primary) 10%, transparent); }
.network-page .network-summary__icon--amber  { --stat-accent: var(--color-accent-text); --stat-tint: color-mix(in srgb, var(--color-accent-text) 12%, transparent); }
.network-page .network-summary__icon--green  { --stat-accent: var(--color-success-text); --stat-tint: color-mix(in srgb, var(--color-success-text) 12%, transparent); }
.network-page .network-summary__icon--pink   { --stat-accent: var(--color-danger); --stat-tint: color-mix(in srgb, var(--color-danger) 10%, transparent); }

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .network-page .network-summary__icon { background: var(--color-bg-alt); }
}

.network-page .network-summary__figures {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.network-page .network-summary__count {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  color: var(--color-ink-heading);
}

.network-page .network-summary__label {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
}

/* Shown only while something is actually waiting — see the template. */
.network-page .network-summary__flag {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--color-danger);
}

/* ---- Sidebar panels ---- */
.network-page .net-panel {
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  margin-bottom: var(--space-4);
}

.network-page .net-panel__head { margin-bottom: var(--space-3); }

.network-page .net-panel__title {
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

/* ---- At a glance ---- */
.network-page .net-glance,
.network-page .net-activity {
  margin: 0;
  padding: 0;
  list-style: none;
}

.network-page .net-glance__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  min-width: 0;
  color: var(--color-ink);
}

.network-page .net-glance__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  color: var(--stat-accent, var(--color-primary));
  background: var(--stat-tint, var(--color-bg-alt));
}

.network-page .net-glance__icon--green  { --stat-accent: var(--color-success-text); --stat-tint: color-mix(in srgb, var(--color-success-text) 12%, transparent); }
.network-page .net-glance__icon--amber  { --stat-accent: var(--color-accent-text); --stat-tint: color-mix(in srgb, var(--color-accent-text) 12%, transparent); }
.network-page .net-glance__icon--blue   { --stat-accent: var(--color-secondary-text); --stat-tint: color-mix(in srgb, var(--color-brand-blue) 12%, transparent); }
.network-page .net-glance__icon--indigo { --stat-accent: var(--color-primary); --stat-tint: color-mix(in srgb, var(--color-primary) 10%, transparent); }

.network-page .net-glance__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
}

.network-page .net-glance__title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  overflow-wrap: anywhere;
}

.network-page .net-glance__sub,
.network-page .net-activity__when {
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

/* Muted until hover, so a column of chevrons does not read as a column
   of calls to action. */
.network-page .net-glance__go { color: var(--color-border); flex-shrink: 0; }
.network-page .net-glance__link:hover .net-glance__go { color: var(--color-primary); }

/* ---- Recent activity ---- */
.network-page .net-activity__item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border-soft);
}

.network-page .net-activity__item:last-child { border-bottom: 0; }

.network-page .net-activity__avatar-img {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.network-page .net-activity__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.network-page .net-activity__who {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

.network-page .net-activity__what {
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-ink-soft);
  overflow-wrap: anywhere;
}

.network-page .net-activity__icon { color: var(--color-text-muted); flex-shrink: 0; }

/* ---- Grow your network ---- */
.network-page .net-grow {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-primary) 7%, transparent);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .network-page .net-grow { background: var(--color-bg-alt); }
}

.network-page .net-grow__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-bottom: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-primary);
}

.network-page .net-grow__title {
  margin: 0 0 var(--space-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-primary);
}

.network-page .net-grow__text {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-ink-soft);
}

.network-page .net-grow__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* ===============================================================
   NETWORK — search + sort tools
   =============================================================== */
.network-page .network-list__tools {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

.network-page .network-list__search {
  position: relative;
  display: flex;
  align-items: center;
  min-width: 0;
}

.network-page .network-list__search-icon {
  position: absolute;
  inset-inline-start: var(--space-3);
  display: inline-flex;
  color: var(--color-text-muted);
  pointer-events: none;
}

.network-page .network-list__search-input {
  width: 220px;
  max-width: 100%;
  height: 40px;
  padding-inline: var(--space-8) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg);
  font-size: var(--fs-sm);
  color: var(--color-ink);
}

.network-page .network-list__search-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.network-page .network-list__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  padding-inline: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg);
  font-size: var(--fs-sm);
  color: var(--color-ink);
  cursor: pointer;
}

/* Pressed state is a real state, not just a colour: the button also
   reports it through aria-pressed. */
.network-page .network-list__sort.is-active {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

/* ===============================================================
   NETWORK — MOBILE (≤767px)
   =============================================================== */
@media (max-width: 767px) {
  /* ---- Summary: icon above the number, four across ----
     !important is required: a later, unconditional rule for this same
     selector (the dark-panel redesign, further down this file) sets
     grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) with
     no media query, so at equal specificity it wins here regardless
     of viewport — and on a phone-width screen, minmax(150px, ...)
     only fits two columns, producing a 2x2 grid instead of one row of
     four. Without !important this rule is silently dead. */
  .network-page .network-summary {
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: var(--space-1);
    padding: var(--space-3);
  }

  .network-page .network-summary__link {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-2);
  }

  .network-page .network-summary__icon {
    width: 40px;
    height: 40px;
  }

  .network-page .network-summary__figures { align-items: center; }

  .network-page .network-summary__count { font-size: var(--fs-md); }

  .network-page .network-summary__label,
  .network-page .network-summary__flag {
    font-size: 10px;
    line-height: 1.2;
  }

  /* ---- Tabs: all five in one fixed row, no scrolling ----
     A grid rather than a flex row: five equal columns guarantee every
     tab fits the viewport width exactly once, with no scroll gesture
     needed to reach the later ones and no risk of wrapping onto a
     second line. Icon, label and count are all sized down from the
     desktop tab so "Connections" and "Followers" — the two longest
     labels — still fit their column on a narrow phone. */
  .network-page .network-tabs {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 2px;
    overflow: visible;
  }

  .network-page .network-tab {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 2px;
    padding: var(--space-2) 2px;
    font-size: 10px;
    line-height: 1.15;
    text-align: center;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  /* Smaller than the theme-wide .icon--sm so five columns have room
     for the label beneath without forcing a wider column. */
  .network-page .network-tab__icon svg.icon {
    width: 14px !important;
    height: 14px !important;
  }

  .network-page .network-tab__count {
    padding: 0 5px;
    font-size: 9px;
    line-height: 1.4;
  }

  /* ---- List header stacks; tools go full width ---- */
  .network-page .network-list__head {
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  .network-page .network-list__tools { width: 100%; }

  .network-page .network-list__search { flex: 1 1 auto; }

  .network-page .network-list__search-input { width: 100%; }

  /* Icon-only sort on a phone: the row has no width to spare, and the
     icon carries the meaning with an accessible name behind it. */
  .network-page .network-list__sort {
    width: 40px;
    padding-inline: 0;
    justify-content: center;
  }

  .network-page .network-list__sort-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* ---- Rows: card per person, actions on their own line ---- */
  .network-page .network-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-2) var(--space-3);
    padding: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-bg);
    margin-bottom: var(--space-3);
  }

  .network-page .network-row__body { grid-column: 2; }

  /* Expertise is hidden on tablet by an earlier rule; on a phone the
     card has room for it below the name, which is what the design
     shows. */
  .network-page .network-row__expertise {
    display: block;
    grid-column: 1 / -1;
  }

  .network-page .network-row__expertise-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
  }

  .network-page .network-row__actions {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--space-2);
  }
}

/* ===============================================================
   NETWORK ROW — presence dot and location pin
   =============================================================== */

/* The dot sits on the avatar, so the avatar is the positioning
   context. Only added when the member has been active within a day —
   see the note in the template on why this is "recently active"
   rather than "online". */
.network-page .network-row__avatar {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
}

.network-page .network-row__avatar.is-active::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  width: 12px;
  height: 12px;
  border-radius: var(--radius-full);
  background: var(--color-success);
  /* Ring in the page background so the dot reads as sitting on top of
     the avatar rather than being part of the photograph. */
  border: 2px solid var(--color-bg);
}

/* The state is also announced in text beside it, so the colour is not
   carrying the meaning alone. */

.network-page .network-row__where-bit {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 0;
}

.network-page .network-row__where-bit .icon {
  flex-shrink: 0;
  color: var(--color-text-muted);
}

/* ===============================================================
   NETWORK HERO STRIP — intro + Connect / Collaborate / Grow
   ===============================================================
   One card, one row: the member's own intro on the left, then the
   three value props from the wireframe on the right, separated by a
   divider. Kept to a single row at every width — see the ≤767px block
   below — rather than the intro/value-props stacking, since the whole
   point of the redesign was to stop this header wrapping onto extra
   lines on a phone.
   =============================================================== */
.network-page .network-hero-strip {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-white);
}

.network-page .network-hero-strip__intro {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Shrinks before the three items do, but not below its content:
     flex-shrink: 0 here meant the intro kept its full width on a
     tablet and squeezed the items until their text overlapped. */
  flex: 0 1 auto;
  min-width: 0;
}

.network-page .network-hero-strip__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
  color: var(--color-primary);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .network-page .network-hero-strip__avatar { background: var(--color-bg-alt); }
}

.network-page .network-hero-strip__intro-text { min-width: 0; }

.network-page .network-hero-strip__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  color: var(--color-ink-heading);
  white-space: nowrap;
}

.network-page .network-hero-strip__badge {
  display: inline-flex;
  color: var(--color-primary);
}

.network-page .network-hero-strip__subtitle {
  margin: 2px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Divider + the three items. A real border-left rather than a
   background line, so it disappears cleanly if the items ever wrap
   onto their own row on a very narrow view. */
.network-page .network-hero-strip__items {
  /* Grid, not flex.
     As a flex row each item sized to its own content, and because the
     titles and descriptions were nowrap, a long description simply
     overran the next item's icon instead of wrapping — the text
     overlapped rather than the box growing. Three equal columns give
     every item a real, bounded width to wrap inside. */
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0 0 0 var(--space-5);
  list-style: none;
  border-left: 1px solid var(--color-border);
  gap: var(--space-5);
}

.network-page .network-hero-strip__item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-width: 0;
}

/* Without this the text column refuses to shrink below its longest
   word and pushes past the grid track. */
.network-page .network-hero-strip__item-text { min-width: 0; }

.network-page .network-hero-strip__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--item-tint, var(--color-bg-alt));
  color: var(--item-accent, var(--color-primary));
}

.network-page .network-hero-strip__icon--indigo {
  --item-accent: var(--color-primary);
  --item-tint: color-mix(in srgb, var(--color-primary) 10%, transparent);
}

.network-page .network-hero-strip__icon--blue {
  --item-accent: var(--color-secondary-text);
  --item-tint: color-mix(in srgb, var(--color-brand-blue) 10%, transparent);
}

.network-page .network-hero-strip__icon--green {
  --item-accent: var(--color-success-text);
  --item-tint: color-mix(in srgb, var(--color-success-text) 10%, transparent);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .network-page .network-hero-strip__icon { background: var(--color-bg-alt); }
}

.network-page .network-hero-strip__item-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.network-page .network-hero-strip__item-title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  /* Titles are one or two words and fit; descriptions wrap to a second
     line rather than running into the neighbouring item. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.network-page .network-hero-strip__item-desc {
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--color-text-muted);
  overflow-wrap: break-word;
}

/* ---- Tablet / narrow desktop: descriptions go ----
   Between roughly 768px and 1100px there is room for the intro and
   three labelled icons, but not for three descriptions as well —
   that is the width at which the text was overlapping. The
   descriptions are the least load-bearing part of the strip, so they
   go first and everything stays on one line. */
@media (max-width: 1100px) {
  .network-page .network-hero-strip__item-desc { display: none; }

  .network-page .network-hero-strip__item { align-items: center; }

  .network-page .network-hero-strip__items { gap: var(--space-4); }
}

/* ---- Mobile: icons only ----
   "My network" plus three icon+label pairs does not fit a phone. The
   labels were nowrap inside grid tracks narrower than the words, so
   "Connect" and "Collaborate" ran over their neighbours' icons instead
   of truncating.

   Shrinking the type further would have made it unreadable, so the
   labels go entirely and the three icons stand alone: they are tinted,
   distinct, and repeat the same three ideas already stated in the
   heading. The text is kept for screen readers (clipped, not
   display:none) so the meaning is not lost to anyone who cannot see
   the icons. */
@media (max-width: 767px) {
  .network-page .network-hero-strip {
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    overflow-x: hidden;
  }

  .network-page .network-hero-strip__avatar {
    width: 36px;
    height: 36px;
  }

  .network-page .network-hero-strip__avatar svg.icon {
    width: 18px !important;
    height: 18px !important;
  }

  .network-page .network-hero-strip__title { font-size: var(--fs-md); }

  .network-page .network-hero-strip__subtitle { display: none; }

  /* Icons only, so the track no longer has to hold a word: they sit at
     their own size against the right edge instead of in three equal
     columns sized for text that is no longer there. */
  .network-page .network-hero-strip__items {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: var(--space-3);
    padding-left: var(--space-3);
  }

  .network-page .network-hero-strip__item {
    align-items: center;
    gap: 0;
  }

  .network-page .network-hero-strip__icon {
    width: 34px;
    height: 34px;
  }

  /* Clipped rather than removed: display:none would drop these from
     the accessibility tree along with the layout, leaving three
     unlabelled icons for a screen reader. */
  .network-page .network-hero-strip__item-title,
  .network-page .network-hero-strip__item-desc {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* Narrowest phones: the intro's own gap and avatar shrink a little
   further so three items plus "My network" still clear the width
   without the row wrapping. */
@media (max-width: 360px) {
  .network-page .network-hero-strip { gap: var(--space-2); }
  .network-page .network-hero-strip__intro { gap: var(--space-2); }
  .network-page .network-hero-strip__items { gap: var(--space-2); padding-left: var(--space-2); }
  .network-page .network-hero-strip__icon { width: 30px; height: 30px; }
}

/* ===============================================================
   NETWORK SIDEBAR — panel links, glance cards, activity rows
   =============================================================== */
.network-page .net-panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.network-page .net-panel__link {
  flex-shrink: 0;
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--color-secondary-text);
}

/* ---- Glance: each metric is its own bordered card ---- */
.network-page .net-glance__item + .net-glance__item { margin-top: var(--space-2); }

.network-page .net-glance__link {
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color var(--transition-fast);
}

.network-page .net-glance__link:hover,
.network-page .net-glance__link:focus-visible {
  border-color: var(--color-primary);
}

/* ---- Activity: avatar with a type badge ---- */
.network-page .net-activity__avatar {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
}

.network-page .net-activity__badge {
  position: absolute;
  right: -4px;
  bottom: -4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-primary);
  /* Ring in the page background so the badge reads as sitting on the
     avatar rather than being part of the photograph. */
  border: 1px solid var(--color-border);
}

.network-page .net-activity__badge .icon {
  width: 10px !important;
  height: 10px !important;
}

/* Line one: who, and what they did. */
.network-page .net-activity__line {
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-ink-soft);
  overflow-wrap: anywhere;
}

.network-page .net-activity__who {
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

/* Line two: the thing itself. */
.network-page .net-activity__what {
  display: block;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

a.net-activity__what:hover,
a.net-activity__what:focus-visible { color: var(--color-primary); }

/* ===============================================================
   NETWORK — filter, overflow menu, "view more"
   =============================================================== */
.network-page .network-list__filter {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.network-page .network-list__filter-icon {
  position: absolute;
  inset-inline-start: var(--space-3);
  display: inline-flex;
  color: var(--color-text-muted);
  pointer-events: none;
}

.network-page .network-list__filter-select {
  height: 40px;
  padding-inline: var(--space-8) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg);
  font-size: var(--fs-sm);
  color: var(--color-ink);
  cursor: pointer;
  /* The native arrow sits too close to the pill edge; the padding
     above leaves room for it without a custom control that would cost
     the keyboard and touch behaviour a <select> gives free. */
  max-width: 190px;
}

/* ---- Overflow menu ---- */
.network-page .network-row__more { position: relative; flex-shrink: 0; }

.network-page .network-row__more-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: var(--radius-full);
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
}

.network-page .network-row__more-btn:hover,
.network-page .network-row__more-btn:focus-visible {
  background: var(--color-bg-alt);
  color: var(--color-ink);
}

.network-page .network-row__more-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  inset-inline-end: 0;
  z-index: var(--z-dropdown);
  min-width: 190px;
  padding: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: var(--shadow-lg);
}

.network-page .network-row__more.is-open .network-row__more-panel { display: block; }

.network-page .network-row__more-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  font-size: var(--fs-sm);
  color: var(--color-ink);
  text-align: start;
  cursor: pointer;
}

.network-page .network-row__more-item:hover,
.network-page .network-row__more-item:focus-visible { background: var(--color-bg-alt); }

/* ---- "View N more" ---- */
.network-page .network-list__more {
  margin: var(--space-4) 0 0;
  text-align: center;
}

.network-page .network-list__more-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-full);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-primary);
}

.network-page .network-list__more-btn:hover,
.network-page .network-list__more-btn:focus-visible { background: var(--color-bg-alt); }

/* The chevron points down: this reveals more of the list rather than
   navigating sideways. */
.network-page .network-list__more-chevron {
  display: inline-flex;
  transform: rotate(90deg);
}

/* Numbers on desktop, the single large target on a phone. Both are in
   the markup; only one is shown at a time. */
@media (max-width: 767px) {
  .network-page .articles-pagination { display: none; }
  .network-page .network-list__filter-select { max-width: 100%; }
}

@media (min-width: 768px) {
  .network-page .network-list__more { display: none; }
}

/* ===============================================================
   NETWORK — summary trends, discover card, grow stack
   =============================================================== */

/* Month-on-month movement under each metric. Only ever an increase —
   see NetworkInsights::summaryTrends() — so the success token is
   always correct here. Text token, not the fill: this is small text. */
.network-page .network-summary__trend {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--color-success-text);
}

/* ---- Discover opportunities (right sidebar) ---- */
.network-page .net-discover {
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--color-primary) 7%, transparent);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .network-page .net-discover { background: var(--color-bg-alt); }
}

.network-page .net-discover__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-bottom: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-primary);
}

.network-page .net-discover__title {
  margin: 0 0 var(--space-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-primary);
}

.network-page .net-discover__text {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-ink-soft);
}

.network-page .net-discover__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* ---- Grow card: overlapping faces ----
   Not scoped to .network-page: the card renders in the sidebar, which
   is outside that wrapper. */
.net-grow__stack {
  display: flex;
  align-items: center;
  margin: var(--space-3) 0 0;
}

.net-grow__face { display: inline-flex; }

/* Overlap, with a ring in the card's own background so each face reads
   as in front of the one behind it. */
.net-grow__face + .net-grow__face { margin-inline-start: -10px; }

.net-grow__face-img {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  border: 2px solid var(--color-bg);
}

.net-grow__count {
  margin-inline-start: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-bg);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--color-secondary-text);
}

.net-grow__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}


/* ---------------------------------------------------------------
   Touch targets — 44x44 minimum, per the specification.
   ---------------------------------------------------------------
   These controls were 32–40px: comfortable with a mouse, below the
   comfortable minimum for a thumb. On a horizontally scrolling list a
   near-miss is worse than a no-op, because it becomes a scroll.

   The visible box is not always grown to 44px — that would crowd the
   card corners the design keeps clear. Where the control should stay
   visually small, the target is extended with padding instead, which
   enlarges the hit area without changing what is drawn.
   --------------------------------------------------------------- */
@media (max-width: 1023px) {
  .network-page .network-row__more-btn,
  .network-page .network-list__sort,
  .network-page .network-list__filter-select,
  .network-page .net-glance__link,
  .network-page .network-list__more-btn {
    min-height: 44px;
  }

  .network-page .network-row__more-btn,
  .network-page .network-list__sort {
    min-width: 44px;
  }

  /* The kebab stays a 36px circle visually; the extra 4px each side is
     hit area only. */
  .network-page .network-row__more-btn {
    width: 44px;
    height: 44px;
  }

  .network-page .network-list__filter-select {
    /* A select's own height is the target, so it is raised directly. */
    height: 44px;
  }
}

/* Pointer devices keep the tighter sizing: 44px targets in a dense
   list are wasted space when the input is a cursor. */


/* ===============================================================
   PEOPLE YOU MAY KNOW — mobile scroller
   ===============================================================
   The card row scrolls horizontally on a phone. Two things were wrong:
   nothing indicated that it scrolled, and long names and roles ran out
   of their cards.
   =============================================================== */
@media (max-width: 1023px) {
  .network-page .network-layout__aside .pymk {
    /* The fade is painted on the module, so it sits over the scroller
       rather than scrolling away with it. */
    position: relative;
  }

  /* A soft edge on the right: the standard, unobtrusive signal that
     there is more beyond the fold. Not a scrollbar — mobile browsers
     hide those — and not arrows, which need a tap target each. */
  .network-page .network-layout__aside .pymk::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 32px;
    pointer-events: none;
    background: linear-gradient(to left, var(--color-bg), transparent);
  }

  /* Text must wrap inside its card rather than widening it. Long
     single tokens — a hyphenated role, a URL-like handle — break
     rather than overflow. */
  .network-page .pymk__name,
  .network-page .pymk__headline,
  .network-page .pymk__reason {
    min-width: 0;
    max-width: 100%;
    overflow-wrap: anywhere;
    white-space: normal;
  }

  /* The card itself must not grow to fit its content. */
  .network-page .pymk__item,
  .network-page .pymk__body {
    min-width: 0;
    max-width: 100%;
  }

  /* Buttons stay inside the card. */
  .network-page .pymk__action,
  .network-page .pymk__action .btn {
    max-width: 100%;
  }
}

/* ===============================================================
   NETWORK — activity empty state
   =============================================================== */

/* Empty state for the activity feed. Rendered rather than hidden, so
   the panel is never mistaken for a missing feature. */
.network-page .net-activity__empty {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-text-muted);
}

/* ===============================================================
   NETWORK SUMMARY — dark panel with an inset insight
   ===============================================================
   The design turns the stat row into a dark band. It is not just
   decoration: it separates "your numbers" from "your people" without
   another border, and it gives the coloured icon chips something to
   sit against.

   Colours inside are literal, not tokens. The panel is dark in BOTH
   colour schemes, so a token that flips in dark mode would invert the
   text out of sight — the same fault that hit the Passport card.
   =============================================================== */
.network-page .network-summary {
  position: relative;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  align-items: center;
  padding: var(--space-5);
  border: 0;
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #14152B 0%, #1E1B45 100%);
}

.network-page .network-summary__link { color: #FFFFFF; }

.network-page .network-summary__count { color: #FFFFFF; }

.network-page .network-summary__label { color: rgba(255, 255, 255, 0.62); }

/* The icon chips keep their hues but need a darker wash to read on the
   panel rather than the page. */
.network-page .network-summary__icon {
  background: rgba(255, 255, 255, 0.08);
}

.network-page .network-summary__icon--indigo { color: #A9A0FF; }
.network-page .network-summary__icon--amber  { color: #FFC46B; }
.network-page .network-summary__icon--green   { color: #6EE7A8; }
.network-page .network-summary__icon--pink    { color: #FF8FB1; }

.network-page .network-summary__trend { color: #6EE7A8; }
.network-page .network-summary__flag  { color: #FF8FB1; }

@media (max-width: 767px) {
  .network-page .network-summary { padding: var(--space-4); }
}

/* ===============================================================
   OVERFLOW MENU — never off the edge
   ===============================================================
   The panel is anchored to the row's right edge, which is the page
   edge on a phone. Anchoring it to the LEFT of the button instead
   would push it off the other side, so it is right-aligned and capped
   to the viewport, with the row allowed to clip nothing.
   =============================================================== */
.network-page .network-row__more-panel {
  max-width: calc(100vw - var(--space-6));
}

/* The row must not clip the open menu. */
.network-page .network-row { overflow: visible; }

/* ---- Row actions stay on ONE line ----
   .rel-actions is flex-wrap: wrap globally (legacy-overrides.css),
   which is right on a profile card where the buttons have the full
   column. In a network row they share a narrow auto-sized grid track
   with the ⋮ menu, so wrapping put Message above Connected on desktop
   and pushed the ⋮ onto a third line on mobile. Scoped to this page so
   the profile card keeps its own behaviour. */
.network-page .network-row__actions {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-2);
}

.network-page .network-row__actions .rel-actions {
  flex-wrap: nowrap;
  gap: var(--space-2);
}

/* Buttons shrink rather than wrap, and their labels stay intact. */
.network-page .network-row__actions .btn {
  flex: 0 1 auto;
  min-width: 0;
  white-space: nowrap;
}

/* The ⋮ never shrinks and never wraps — it is the last thing that
   should give way when the row is tight. */
.network-page .network-row__more { flex: 0 0 auto; }

@media (max-width: 767px) {
  /* On a phone the actions drop to their own full-width line under the
     name (grid-column: 1 / -1 above), where they sit in a single row
     with the ⋮ pushed to the right edge. */
  .network-page .network-row__actions {
    flex-wrap: nowrap;
    width: 100%;
  }

  .network-page .network-row__more { margin-inline-start: auto; }

  /* Labels can ellipsize on the narrowest phones rather than forcing
     the row wider than the screen. */
  .network-page .network-row__actions .btn {
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ===============================================================
   RELATIONSHIP MENU — submenus and the shared-activity panel
   ===============================================================
   New rules for a component whose base styles live in
   legacy-overrides.css. They go here rather than there because that
   file only ever shrinks (see its header), and identity-components.css
   is bundled after it — so plain class selectors win without needing
   !important or a wrapper prefix.
   =============================================================== */

/* A nested <details> inside the menu panel: same row treatment as a
   plain item, with a chevron that turns when it opens. */
.rel-menu__sub { width: 100%; }

.rel-menu__item--sub {
  justify-content: space-between;
  gap: var(--space-2);
  /* <summary> shows a disclosure triangle by default, which would sit
     beside our own chevron. */
  list-style: none;
}

.rel-menu__item--sub::-webkit-details-marker { display: none; }
.rel-menu__item--sub::marker { content: ''; }

.rel-menu__chevron {
  flex-shrink: 0;
  width: 0;
  height: 0;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 5px solid currentColor;
  transition: transform var(--transition-fast);
}

.rel-menu__sub[open] > .rel-menu__item--sub > .rel-menu__chevron {
  transform: rotate(90deg);
}

.rel-menu__sub-panel {
  padding: var(--space-2) var(--space-3) var(--space-2);
  margin: 2px 0 var(--space-1);
  border-left: 2px solid var(--color-border);
  margin-inline-start: var(--space-3);
}

.rel-menu__sub-loading {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

/* ---- Shared activity figures ---- */
.shared-activity__line {
  margin: 0 0 2px;
  font-size: var(--fs-xs);
  color: var(--color-ink-soft);
  /* Topic names can be long; the menu must not stretch to fit them. */
  white-space: normal;
  overflow-wrap: anywhere;
}

.shared-activity__count {
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  font-variant-numeric: tabular-nums;
}

.shared-activity__topics {
  margin: 0 0 var(--space-2);
  padding: 0 0 0 var(--space-3);
  list-style: none;
}

.shared-activity__topic {
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.shared-activity__topic::before {
  content: '\2022';
  margin-inline-end: var(--space-2);
  color: var(--color-primary);
}

/* The panel carries wrapping text, so the menu needs a real width
   rather than the nowrap-driven one the plain items give it. */
.rel-menu__panel:has(.rel-menu__sub) { min-width: 240px; }

/* ---- Row meta: connected since / last active ----
   The row's quietest line: it sits under the expertise tags and is
   context, not content, so it takes the muted colour and the smallest
   size rather than competing with the name above it. */
.network-page .network-row__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

.network-page .network-row__meta-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--color-text-muted);
}

.network-page .network-row__meta-bit { white-space: nowrap; }

@media (max-width: 640px) {
  /* Wraps to its own line on a phone rather than pushing the row
     wider; the two halves stay whole, so "Last active 3 days ago" is
     never split across lines mid-phrase. */
  .network-page .network-row__meta { gap: var(--space-1) var(--space-2); }
}

/* ---- Mobile "+" sheet: divider above Sign out ----
   Sign out is the one non-create item in this sheet (see
   template-parts/footer/mobile-nav.php), so it needs a visible break
   from the create actions above it — otherwise it reads as a fourth
   thing to create. */
.mobile-quick-actions__divider {
  height: 1px;
  margin: var(--space-2) 0;
  background: var(--color-border);
}

/* ===============================================================
   NETWORK ROW — explicit grid placement for the ⋮
   ===============================================================
   The row has FIVE children: avatar, body, expertise, actions and the
   ⋮ menu — and .network-row__more is a sibling of .network-row__actions,
   not a child of it. Every grid definition for this row declared four
   columns or fewer, so the ⋮ was auto-placed into an implicit track
   past the last one: on desktop it landed on top of the Connected
   button, and on mobile it dropped to a line of its own.

   Placement is stated explicitly here rather than left to auto-flow,
   because the expertise column is display:none below 1024px — which
   removes it from the grid entirely and shifts everything after it by
   one track. Auto-placement therefore cannot be correct at both widths
   at once.
   =============================================================== */

/* ---- Desktop: one row, five tracks ---- */
@media (min-width: 1024px) {
  .network-page .network-row {
    grid-template-columns: auto minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
  }

  .network-page .network-row__avatar    { grid-column: 1; grid-row: 1; }
  .network-page .network-row__body      { grid-column: 2; grid-row: 1; }
  .network-page .network-row__expertise { grid-column: 3; grid-row: 1; }
  .network-page .network-row__actions   { grid-column: 4; grid-row: 1; }
  .network-page .network-row__more      { grid-column: 5; grid-row: 1; }
}

/* ---- Tablet: expertise is hidden, so four tracks ---- */
@media (min-width: 768px) and (max-width: 1023px) {
  .network-page .network-row {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
  }

  .network-page .network-row__avatar  { grid-column: 1; grid-row: 1; }
  .network-page .network-row__body    { grid-column: 2; grid-row: 1; }
  .network-page .network-row__actions { grid-column: 3; grid-row: 1; }
  .network-page .network-row__more    { grid-column: 4; grid-row: 1; }
}

/* ---- Mobile: name on line one, actions and ⋮ together on line two ----
   The ⋮ shares the actions' line at the right edge rather than taking
   a third line of its own, which is what the mockup shows and what
   keeps the card to two lines. */
@media (max-width: 767px) {
  .network-page .network-row {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
  }

  .network-page .network-row__avatar { grid-column: 1; grid-row: 1; }
  .network-page .network-row__body   { grid-column: 2 / 4; grid-row: 1; }

  .network-page .network-row__actions {
    grid-column: 1 / 3;
    grid-row: 2;
    justify-content: flex-start;
  }

  .network-page .network-row__more {
    grid-column: 3;
    grid-row: 2;
    justify-self: end;
    align-self: center;
    /* Cancels the auto margin an earlier rule used to push it right
       when it was (wrongly) treated as a flex sibling. */
    margin-inline-start: 0;
  }
}

/* ---- Connected as a state, not a control ----
   On the network row the ⋮ owns every action, so the state reads as a
   label. Same pill shape and colour as the button it replaces, without
   the affordances — no caret, no hover, no pointer — so nothing invites
   a click that does nothing. */
.network-page .rel-state {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-success-text);
  border-radius: var(--radius-full);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-success-text);
  background: transparent;
  white-space: nowrap;
}

.network-page .rel-state.btn--sm {
  padding: 6px var(--space-3);
  font-size: var(--fs-xs);
}

.network-page .rel-state__check { line-height: 1; }

/* ---- ⋮ panel now carries the relationship menu ----
   The panel keeps its own positioning (absolute, right-aligned, opened
   by the is-open class the dropdown script sets) but its contents are
   now rel-menu items. The rel-menu__panel class it also carries is a
   static block elsewhere, so its display and position must not leak in
   here and override the dropdown's own show/hide. */
.network-page .network-row__more-panel.rel-menu__panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  inset-inline-end: 0;
  inset-inline-start: auto;
  min-width: 232px;
  max-width: min(280px, calc(100vw - var(--space-6)));
}

.network-page .network-row__more.is-open .network-row__more-panel.rel-menu__panel {
  display: block;
}

/* ===============================================================
   CONFIRMATION DIALOGS — stacking
   ===============================================================
   A modal <dialog> is painted in the browser's top layer, above every
   z-index on the page, so this is belt-and-braces for the non-modal
   path: where showModal() is unavailable or a dialog is opened with
   show(), it would otherwise fall back into normal stacking and could
   land beneath the mobile drawer (z-index 100) or a sticky header.
   =============================================================== */
.confirm-dialog,
.connect-dialog {
  z-index: var(--z-dialog);
}

/* The page must not scroll behind an open confirmation on touch, where
   a scroll started on the backdrop otherwise moves the list underneath
   and the member loses their place. */
body:has(.confirm-dialog[open]),
body:has(.connect-dialog[open]) {
  overflow: hidden;
}

/* ===============================================================
   NETWORK ROW — rows without expertise tags
   ===============================================================
   .network-row__expertise is only rendered when the member has
   jdev_stack terms, but the grid reserved its 1fr track regardless.
   On a row with no tags that track sat empty and still took its share
   of the width, squeezing the body column: the headline hit its
   ellipsis while a third of the row was blank, and the meta line was
   narrow enough that its icon and text fell onto separate lines.

   :has() lets the row drop the track when the element is not there.
   =============================================================== */
@media (min-width: 1024px) {
  .network-page .network-row:not(:has(.network-row__expertise)) {
    grid-template-columns: auto minmax(0, 1fr) auto auto;
  }

  .network-page .network-row:not(:has(.network-row__expertise)) .network-row__actions {
    grid-column: 3;
  }

  .network-page .network-row:not(:has(.network-row__expertise)) .network-row__more {
    grid-column: 4;
  }
}

/* ---- Headline: two lines, not one clipped line ----
   nowrap + ellipsis cut "Technical Architect, Enterprise Systems" to
   "Technical Archite…" even where the row had room. The headline is
   how a member is identified professionally, so it gets two lines and
   only then clamps. */
.network-page .network-row__headline {
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ---- Meta line: icon and text stay together ----
   The icon is part of the first phrase, not a separate item that may
   wrap onto its own line above the text. */
.network-page .network-row__meta {
  flex-wrap: wrap;
  row-gap: 2px;
}

/* The icon now sits inside the first phrase (see list.php), so it
   simply aligns with the text rather than needing to be pulled back
   toward it. */
.network-page .network-row__meta-bit {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
}

.network-page .network-row__meta-icon {
  display: inline-flex;
  flex-shrink: 0;
}

/* Separator between the meta phrases, drawn rather than marked up: the
   dot belongs to the gap between two phrases, not to either of them,
   and as a real element it was one more flex item that could wrap onto
   a line by itself. ::before on all but the first keeps it attached to
   the phrase it precedes. */
.network-page .network-row__meta .network-row__meta-bit + .network-row__meta-bit::before {
  content: '·';
  margin-inline-end: var(--space-2);
  color: var(--color-border);
}

/* ===============================================================
   SUGGESTION HEADING — sentence case, not uppercase
   ===============================================================
   "Professionals to Discover" is a phrase, not a label, so it reads as
   written. A `.profile-shell` rule in legacy-overrides.css applies an
   11px uppercase label treatment to .pymk__title (correct for the
   profile page's section labels, wrong for this heading), and the
   homepage module title inherits the same look from its own heading
   scale.

   Stated here rather than edited there, because that rule is shared
   with several profile card titles where the uppercase IS right —
   this file is bundled after legacy-overrides.css, so a plain
   selector wins without touching them.
   =============================================================== */
.pymk__title,
.profile-shell .pymk__title,
.sih-pymk .home-module__title {
  text-transform: none;
  letter-spacing: normal;
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
}

/* ===============================================================
   FIND AN EXPERT
   ===============================================================
   Desktop lays each card out as four columns — identity, evidence,
   expertise areas, actions — and mobile stacks the same markup in the
   same order. One DOM, two grids, so there is no second copy to keep
   in step.

   The `xd-` prefix keeps this clear of `.member-card`, which the
   Mentor Marketplace still uses.
   =============================================================== */

.expert-directory .container { max-width: 1280px; }

/* ---- Hero ---- */
.xd-hero { padding-block: var(--space-6) var(--space-5); }

/* Title left, trust right, one line on desktop; the trust pill wraps
   under the title on narrower screens rather than squeezing it. */
.xd-hero__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-5);
}

.xd-hero__title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  font-size: var(--fs-3xl);
  font-weight: var(--fw-bold);
  color: var(--color-ink-heading);
}

.xd-hero__mark { display: inline-flex; color: var(--color-primary); }

.xd-hero__lede {
  margin: var(--space-2) 0 0;
  color: var(--color-text-muted);
}

/* The trust line: a claim about method, so it reads as a note rather
   than a banner competing with the title. */
.xd-trust {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--color-bg-alt);
  font-size: var(--fs-sm);
  color: var(--color-ink-soft);
}

.xd-trust__icon { display: inline-flex; color: var(--color-primary); }
.xd-trust__link { color: var(--color-primary); font-weight: var(--fw-semibold); white-space: nowrap; }

/* ---- Filters ---- */
.xd-filters {
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-white);
}

.xd-search {
  position: relative;
  margin-bottom: var(--space-4);
}

.xd-search__icon {
  position: absolute;
  inset-inline-start: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  color: var(--color-text-muted);
  pointer-events: none;
}

.xd-search__input {
  width: 100%;
  padding: var(--space-3) var(--space-3) var(--space-3) calc(var(--space-3) * 2 + 20px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  /* 16px minimum, or iOS zooms the page on focus. */
  font-size: max(16px, var(--fs-sm));
  background: var(--color-bg);
}

.xd-filters__core {
  display: grid;
  /* Three EQUAL field tracks with a floor sized to the longest default
     label ("All technologies" at the desktop control size, icon
     included) — equal tracks are what makes the fields read as the
     same size, and the floor is what guarantees no placeholder ever
     ellipsises. Toggle and buttons take the last two tracks. */
  grid-template-columns: repeat(3, minmax(190px, 1fr)) auto auto;
  gap: var(--space-3) var(--space-4);
  align-items: end;
}

/* Where five tracks no longer fit, the toggle and the buttons drop to
   their own second line rather than squeezing the fields below the
   width their text needs. */
@media (min-width: 768px) and (max-width: 1199px) {
  .xd-filters__core { grid-template-columns: repeat(3, minmax(190px, 1fr)); }

  .xd-filters__field--toggle { grid-column: 1; }

  .xd-filters__actions {
    grid-column: 2 / 4;
    justify-content: flex-end;
  }
}

.xd-filters__field { display: flex; flex-direction: column; gap: 4px; margin: 0; min-width: 0; }

.xd-filters__label {
  font-size: 11px;
  font-weight: var(--fw-bold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.xd-filters__control {
  width: 100%;
  min-height: 44px; /* touch target floor from the spec */
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: max(16px, var(--fs-sm));
  background: var(--color-bg);
  color: var(--color-ink);
}

.xd-filters__actions {
  display: flex;
  gap: var(--space-2);
  margin: 0;
}

.xd-filters__actions .btn { min-height: 44px; white-space: nowrap; }

/* ---- Availability toggle ---- */
.xd-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  cursor: pointer;
}

/* The checkbox stays in the accessibility tree and keeps its own
   keyboard behaviour; only its rendering is replaced. */
.xd-toggle input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.xd-toggle__track {
  position: relative;
  flex-shrink: 0;
  width: 40px;
  height: 22px;
  border-radius: var(--radius-full);
  background: var(--color-border);
  transition: background var(--transition-fast);
}

.xd-toggle__thumb {
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  background: var(--color-white);
  transition: transform var(--transition-fast);
}

.xd-toggle input:checked + .xd-toggle__track { background: var(--color-primary); }
.xd-toggle input:checked + .xd-toggle__track .xd-toggle__thumb { transform: translateX(18px); }
.xd-toggle input:focus-visible + .xd-toggle__track { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.xd-toggle__text { font-size: var(--fs-sm); color: var(--color-ink-soft); }

/* ---- More filters ----
   Always visible on desktop, collapsed behind a toggle on mobile. A
   checkbox (the .xd-more-row__state input) carries the open state so
   both behaviours come from one DOM with no script: desktop hides the
   toggle and shows the row unconditionally; mobile shows the toggle
   and reveals the row only while the box is checked. */
.xd-more-row {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.xd-more-row__toggle {
  display: none; /* desktop: the row is simply there */
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  cursor: pointer;
}

.xd-more-row__caret {
  width: 0;
  height: 0;
  border-inline-start: 5px solid transparent;
  border-inline-end: 5px solid transparent;
  border-top: 6px solid currentColor;
  transition: transform var(--transition-fast);
}

.xd-more-row__state:checked ~ .xd-more-row__toggle .xd-more-row__caret { transform: rotate(180deg); }

.xd-more-row__state:focus-visible ~ .xd-more-row__toggle {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.xd-more-row__apply { margin-inline-start: var(--space-2); }

.xd-more-row__filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  min-width: 0;
}

.xd-more-row__label { margin-inline-end: var(--space-2); white-space: nowrap; }

.xd-pill { display: inline-flex; }

.xd-pill__control {
  min-height: 36px;
  padding: 4px var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg);
  font-size: var(--fs-xs);
  color: var(--color-ink-soft);
  max-width: 150px;
}

.xd-pill__control--text { width: 110px; }

.xd-results__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.xd-results__count { margin: 0; font-weight: var(--fw-semibold); color: var(--color-ink-heading); }

.xd-results__sort {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

.xd-results__sort .xd-filters__label { margin: 0; white-space: nowrap; }
.xd-results__sort .xd-filters__control { width: auto; min-width: 180px; }

/* ---- Card ---- */
.xd-list {
  display: grid;
  gap: var(--space-4);
  margin: var(--space-5) 0 0;
  padding: 0;
  list-style: none;
}

.xd-card {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-white);
}

.xd-card:focus-within { border-color: var(--color-primary); }

.xd-card__identity { display: flex; gap: var(--space-3); min-width: 0; }

.xd-card__avatar { flex-shrink: 0; line-height: 0; }

/* Reserved dimensions: the avatar's box exists before the image loads,
   so a slow image cannot shift the card (CLS). */
.xd-card__avatar img {
  width: 72px;
  height: 72px;
  border-radius: var(--radius-full);
  object-fit: cover;
}

.xd-card__who { min-width: 0; }

.xd-card__name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
}

.xd-card__name a { color: var(--color-ink-heading); text-decoration: none; }
.xd-card__name a:hover { color: var(--color-primary); }

.xd-card__verified { display: inline-flex; flex-shrink: 0; color: var(--color-primary); }

.xd-card__role,
.xd-card__location,
.xd-card__years {
  margin: 2px 0 0;
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.xd-card__location { display: flex; align-items: center; gap: 4px; }
.xd-card__location-icon { display: inline-flex; flex-shrink: 0; }

.xd-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.xd-card__tag {
  padding: 3px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-bg-alt);
  font-size: var(--fs-xs);
  color: var(--color-ink-soft);
}

.xd-card__tag--more { color: var(--color-primary); font-weight: var(--fw-semibold); }

.xd-card__profile-link { margin: var(--space-3) 0 0; font-size: var(--fs-sm); }

.xd-card__profile-link a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--color-primary);
  font-weight: var(--fw-semibold);
}

/* ---- Evidence ---- */
.xd-card__evidence {
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--color-bg-alt);
  min-width: 0;
}

.xd-card__score {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  flex-wrap: wrap;
}

.xd-card__score-value {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.xd-card__score-caption {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  color: var(--color-ink-soft);
}

.xd-card__score-info { display: inline-flex; color: var(--color-text-muted); }
.xd-card__score-info:hover { color: var(--color-primary); }

.xd-meter {
  display: flex;
  height: 8px;
  margin-bottom: var(--space-3);
  border-radius: var(--radius-full);
  background: var(--color-border);
  overflow: hidden;
}

.xd-meter__seg--accepted     { background: var(--color-primary); }
.xd-meter__seg--endorsements { background: var(--color-brand-blue); }
.xd-meter__seg--years        { background: var(--color-border); }

.xd-evidence { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }

.xd-evidence__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--color-ink-soft);
}

/* The key dot repeats the meter's colour, but the text carries the
   meaning — colour is never the only signal. */
.xd-evidence__item::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
  background: currentColor;
}

.xd-evidence__item--accepted::before     { background: var(--color-primary); }
.xd-evidence__item--endorsements::before { background: var(--color-brand-blue); }
.xd-evidence__item--years::before        { background: var(--color-border); }

.xd-card__norecord { margin: 0; font-size: var(--fs-xs); color: var(--color-text-muted); }

/* ---- Top expertise areas ---- */
.xd-card__areas { min-width: 0; }

.xd-card__areas-title {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.xd-card__areas-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }

.xd-card__area {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--color-ink-soft);
  overflow-wrap: anywhere;
}

.xd-card__area-icon { display: inline-flex; flex-shrink: 0; color: var(--color-primary); }

/* ---- Actions ---- */
.xd-card__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  justify-content: flex-end;
}

.xd-card__chips { margin: 0; }

.xd-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px var(--space-2);
  border-radius: var(--radius-full);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}

.xd-chip--mentor {
  background: color-mix(in srgb, var(--color-success-text) 10%, transparent);
  color: var(--color-success-text);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .xd-chip--mentor { background: var(--color-bg-alt); }
}

.xd-card__buttons { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; justify-content: flex-end; }
.xd-card__buttons .btn { min-height: 44px; }

/* The relationship controls stay on ONE line, right-aligned — the
   dropdown states (Following ▾, Requested ▾) are <details>, not .btn,
   and .rel-actions' global flex-wrap stacked them vertically wherever
   the row got tight. Right-justified nowrap keeps every state pair in
   the same position Follow + Connect occupy. */
.xd-card__buttons .rel-actions {
  flex-wrap: nowrap;
  justify-content: flex-end;
  min-width: 0;
}

.xd-card__buttons .rel-menu__button { white-space: nowrap; }

/* ---- Empty, pager, method ---- */
.xd-empty {
  margin-top: var(--space-5);
  padding: var(--space-8) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-white);
  text-align: center;
}

.xd-empty__title { margin: 0 0 var(--space-2); font-size: var(--fs-lg); }
.xd-empty__text { margin: 0 auto; max-width: 52ch; color: var(--color-text-muted); }
.xd-empty__actions { margin: var(--space-4) 0 0; }

.xd-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-5);
}

.xd-pager__step {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-primary);
  font-weight: var(--fw-semibold);
}

.xd-pager__status { margin: 0; font-size: var(--fs-sm); color: var(--color-text-muted); }

.xd-method {
  margin: var(--space-8) 0 var(--space-6);
  padding: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg-alt);
  scroll-margin-top: calc(var(--jdev-header-h, 64px) + var(--space-4));
}

.xd-method__title { margin: 0 0 var(--space-2); font-size: var(--fs-lg); }
.xd-method__text { margin: 0 0 var(--space-3); max-width: 70ch; color: var(--color-ink-soft); }
.xd-method__list { margin: 0 0 var(--space-3); padding-inline-start: var(--space-5); color: var(--color-ink-soft); }
.xd-method__version { margin: 0; font-size: var(--fs-xs); color: var(--color-text-muted); }

/* The kebab sits in the card's own corner, outside the grid flow, so
   it aligns identically on every card regardless of column heights. */
.xd-card { position: relative; }

.xd-card__more { position: absolute; top: var(--space-3); inset-inline-end: var(--space-3); z-index: 2; }

.xd-card__more-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
}

.xd-card__more-btn:hover,
.xd-card__more-btn:focus-visible { background: var(--color-bg-alt); color: var(--color-ink); }

.xd-card__more-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  inset-inline-end: 0;
  z-index: var(--z-dropdown);
  min-width: 170px;
  padding: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: var(--shadow-lg);
}

.xd-card__more.is-open .xd-card__more-panel { display: block; }

.xd-card__more-item {
  display: flex;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-size: var(--fs-sm);
  color: var(--color-ink);
  text-align: start;
  cursor: pointer;
  text-decoration: none;
}

.xd-card__more-item:hover,
.xd-card__more-item:focus-visible { background: var(--color-bg-alt); }

.xd-card__more-item--danger { color: var(--color-danger); }

.xd-card__more-panel form { margin: 0; }

.xd-card__bio {
  margin: var(--space-3) 0 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--color-ink-soft);
  overflow-wrap: anywhere;
}

/* ===============================================================
   DESKTOP — three columns, actions as the right column's bottom row
   =============================================================== */
@media (min-width: 1024px) {
  .xd-card {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, .9fr);
    /* Actions span the evidence + areas width on the bottom row, not
       just the areas column. Two dropdowns ("Following" + "Requested")
       did not fit the .9fr track, so .rel-actions' flex-wrap stacked
       them vertically mid-card — the full-width bottom row gives every
       relationship state room to sit in one line at the bottom right,
       exactly where Follow + Connect sit. */
    grid-template-areas:
      "identity evidence areas"
      "identity actions actions";
    align-items: start;
    gap: var(--space-4) var(--space-5);
    /* Room for the kebab so the areas column never sits under it. */
    padding-inline-end: calc(var(--space-4) + 40px);
  }

  .xd-card__identity { grid-area: identity; }
  .xd-card__evidence { grid-area: evidence; }
  .xd-card__areas    { grid-area: areas; }

  .xd-card__actions {
    grid-area: actions;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    align-self: end;
  }
}

/* Tablet: identity and evidence side by side, areas and actions below —
   the spec's "condensed" card rather than either extreme. */
@media (min-width: 768px) and (max-width: 1023px) {
  .xd-card {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .xd-card__actions {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* ===============================================================
   MOBILE — stacked card, bottom action row
   =============================================================== */
@media (max-width: 767px) {
  .xd-hero { padding-block: var(--space-4) var(--space-3); }
  .xd-hero__title { font-size: var(--fs-2xl); }

  .xd-trust { width: 100%; flex-wrap: wrap; }

  .xd-filters { padding: var(--space-3); }

  /* The core row can't be one line on a phone: fields pair up two per
     row (Technology+Location, Experience+Availability) and the buttons
     take their own full-width line, per the mobile wireframe. */
  .xd-filters__core { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .xd-filters__actions { grid-column: 1 / -1; }
  .xd-filters__actions .btn { flex: 1 1 auto; justify-content: center; }

  /* Mobile: the toggle shows and the row hides until checked. The
     row's own inline "More filters" eyebrow is redundant beside the
     toggle that says the same thing, so it goes. */
  .xd-more-row__toggle { display: flex; }
  .xd-more-row__label { display: none; }

  .xd-more-row__filters {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
    padding-top: var(--space-2);
  }

  .xd-more-row__state:checked ~ .xd-more-row__filters { display: flex; }

  .xd-pill { width: 100%; }
  .xd-pill__control { width: 100%; max-width: none; }
  .xd-pill__control--text { width: 100%; }
  .xd-more-row__apply { margin: 0; width: 100%; justify-content: center; }

  /* Count left, sort right — one line, per the wireframe. */
  .xd-results__head { flex-wrap: nowrap; }
  .xd-results__count { font-size: var(--fs-sm); white-space: nowrap; }
  .xd-results__sort { min-width: 0; }
  .xd-results__sort .xd-filters__label { display: none; }
  .xd-results__sort .xd-filters__control { flex: 1 1 auto; min-width: 0; max-width: 170px; }

  .xd-card { gap: var(--space-3); }
  .xd-card__avatar img { width: 56px; height: 56px; }
  .xd-card__name { font-size: var(--fs-md); }

  /* Room for the corner ⋮ so the name never runs beneath it. */
  .xd-card { padding-inline-end: calc(var(--space-4) + 36px); }
  .xd-card__actions,
  .xd-card__evidence { margin-inline-end: calc((var(--space-4) + 36px) * -1 + var(--space-4)); }

  /* Evidence per the wireframe: score + bar on the left, the evidence
     list on the right, one compact block. */
  .xd-card__evidence {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--space-2) var(--space-3);
    align-items: center;
  }

  .xd-card__score { grid-column: 1; margin: 0; }
  .xd-meter { grid-column: 1; margin: 0; }
  .xd-evidence { grid-column: 2; grid-row: 1 / 3; align-self: center; }
  .xd-card__norecord { grid-column: 1 / -1; }

  /* Actions become the card's bottom row, per the capability matrix. */
  .xd-card__actions {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-border);
  }

  .xd-card__buttons { flex: 1 1 auto; justify-content: flex-end; }

  .xd-pager { gap: var(--space-2); }
  .xd-pager__step { padding: 0 var(--space-3); }
}

/* Narrowest supported width: nothing may overflow at 320px. */
@media (max-width: 360px) {
  .xd-filters__core { grid-template-columns: minmax(0, 1fr); }

  /* The evidence pair stacks again at the narrowest widths. */
  .xd-card__evidence { grid-template-columns: minmax(0, 1fr); }
  .xd-evidence { grid-column: 1; grid-row: auto; }

  .xd-card__buttons { width: 100%; justify-content: stretch; }
  .xd-card__buttons .btn { flex: 1 1 auto; justify-content: center; }
}

/* 1920+: centred, so the cards do not stretch into unreadable rows. */
@media (min-width: 1920px) {
  .expert-directory .container { max-width: 1440px; }
}

@media (prefers-reduced-motion: reduce) {
  .xd-toggle__track,
  .xd-toggle__thumb,
  .xd-more__caret { transition: none; }
}

/* ===============================================================
   EXPERT DIRECTORY — mobile overflow fixes
   ===============================================================
   Three separate overflows on a phone, all from content being told
   not to wrap inside a box narrower than the content.
   =============================================================== */

/* ---- Native select controls truncate their own text ----
   A <select> does not ellipsize: it clips. With no room reserved for
   the chevron the label ran under it and lost its last characters —
   "All technologies" read as "All technologie". Reserving the arrow's
   width and letting the text ellipsize keeps the truncation legible
   and deliberate. */
select.xd-filters__control {
  padding-inline-end: calc(var(--space-3) + 20px);
  text-overflow: ellipsis;
}

@media (max-width: 767px) {
  /* ---- Results head: count, sort and Apply ----
     nowrap forced all three onto one line, so Apply was pushed off
     the right edge and the sort select was clipped mid-word. They wrap
     to a second line instead: the count reads on its own, and the sort
     control plus Apply share the line below it. */
  .xd-results__head {
    flex-wrap: wrap;
    row-gap: var(--space-3);
  }

  .xd-results__count { flex: 1 1 100%; }

  .xd-results__sort {
    flex: 1 1 auto;
    flex-wrap: nowrap;
    min-width: 0;
  }

  .xd-results__sort .xd-filters__control {
    flex: 1 1 auto;
    min-width: 0;
    /* Was capped at 170px, which clipped "Most relevant". */
    max-width: none;
  }

  .xd-results__apply { flex: 0 0 auto; }

  /* ---- The floating chat button sits over the last control ----
     The dock is fixed to the bottom-right above the tab bar, so the
     final row of any page renders underneath it. Padding at the foot
     of the directory keeps the last control reachable. */
  .expert-directory { padding-bottom: 72px; }

  /* ---- Trust banner: icon, text and link on one block ----
     flex-wrap put the shield alone on the first line with the
     sentence beneath it, which reads as a stray icon. The icon and
     the text belong to one phrase, so the icon stays inline with the
     text and only the "Learn more" link wraps to its own line. */
  .xd-trust {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-1) var(--space-2);
    align-items: start;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-lg);
  }

  .xd-trust__icon { grid-column: 1; grid-row: 1; margin-top: 2px; }
  .xd-trust__text { grid-column: 2; grid-row: 1; }
  .xd-trust__link { grid-column: 2; grid-row: 2; }
}

/* ===============================================================
   FIND AN EXPERT — colour pass + mobile placeholder fit
   ===============================================================
   The gradient and tint treatment from the design, applied as
   decoration only: no colour here carries a meaning the data does not
   have. The alternating card accent is purely visual rhythm — both
   colours mean nothing beyond "not the same card as the one above".
   =============================================================== */

/* ---- Filter card: brand gradient top edge + soft wash ---- */
.xd-filters {
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(135deg,
      color-mix(in srgb, #9333EA 4%, transparent),
      color-mix(in srgb, #3B82F6 4%, transparent) 55%,
      color-mix(in srgb, #22C55E 4%, transparent)),
    var(--color-white);
}

.xd-filters::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, #9333EA, #6D5EF5, #3B82F6, #22C55E);
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .xd-filters { background: var(--color-white); }
}

/* ---- Field icons in the core controls ---- */
.xd-field { position: relative; display: block; }

.xd-field__icon {
  position: absolute;
  inset-inline-start: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  pointer-events: none;
}

.xd-field--tech .xd-field__icon     { color: var(--color-primary); }
.xd-field--location .xd-field__icon { color: #E0447C; }
.xd-field--exp .xd-field__icon      { color: var(--color-success-text); }

.xd-field__control { padding-inline-start: calc(var(--space-2) + 16px + 6px); }

/* Desktop and tablet: 14px control text. The 16px floor exists to stop
   iOS zooming a focused field, which is a touch problem — on a pointer
   device 14px buys every default label whole at the 190px track floor. */
@media (min-width: 768px) {
  .xd-filters__control,
  .xd-pill__control { font-size: 14px; }
}

/* ---- Card: alternating accent, gradient wash, tinted details ---- */
.xd-list .xd-card {
  overflow: hidden;
  border-inline-start: 3px solid var(--xd-accent, var(--color-primary));
  background:
    linear-gradient(120deg,
      color-mix(in srgb, var(--xd-accent, var(--color-primary)) 5%, transparent),
      transparent 45%),
    var(--color-white);
}

.xd-list .xd-card:nth-child(even) { --xd-accent: var(--color-success-text); }

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .xd-list .xd-card { background: var(--color-white); }
}

/* Avatar ring in the card's accent. */
.xd-card__avatar img {
  border: 2px solid color-mix(in srgb, var(--xd-accent, var(--color-primary)) 45%, transparent);
  box-shadow: 0 0 0 2px var(--color-white);
}

/* Tags tinted rather than grey. */
.xd-card__tag {
  background: color-mix(in srgb, var(--xd-accent, var(--color-primary)) 8%, transparent);
  color: color-mix(in srgb, var(--xd-accent, var(--color-primary)) 80%, var(--color-ink));
}

@supports not (color: color-mix(in srgb, red 10%, blue)) {
  .xd-card__tag { background: var(--color-bg-alt); color: var(--color-ink-soft); }
}

/* Score: the accent, and the meter as a gradient of it. */
.xd-card__score-value { color: var(--xd-accent, var(--color-primary)); }

.xd-meter__seg--accepted {
  background: linear-gradient(90deg, var(--xd-accent, var(--color-primary)),
    color-mix(in srgb, var(--xd-accent, var(--color-primary)) 55%, #3B82F6));
}

.xd-evidence__item--accepted::before { background: var(--xd-accent, var(--color-primary)); }

.xd-card__evidence { background: color-mix(in srgb, var(--xd-accent, var(--color-primary)) 4%, var(--color-bg-alt)); }

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .xd-card__evidence { background: var(--color-bg-alt); }
}

/* Area icons pick up the accent too. */
.xd-card__area-icon { color: var(--xd-accent, var(--color-primary)); }

/* ---- Mobile: the placeholders must fit their half-width column ----
   "All technologies" was ellipsising at 16px inside ~160px. The inline
   padding tightens and the field icons hide on a phone, giving the
   text back ~40px — enough for every default label at the 16px size
   iOS requires to not zoom the page on focus. */
@media (max-width: 767px) {
  .xd-field__icon { display: none; }
  .xd-field__control { padding-inline-start: var(--space-2); }
  .xd-filters__control { padding-inline: var(--space-2); }

  /* Native select chrome reserves ~24px for its arrow, which is what
     tipped "All technologies" into an ellipsis at 16px in a half-width
     column. appearance: none takes that space back and a slim drawn
     caret (12px) replaces it, so the full label fits at the 16px size
     iOS needs to not zoom on focus. */
  select.xd-filters__control,
  select.xd-pill__control {
    appearance: none;
    -webkit-appearance: none;
    padding-inline-end: calc(var(--space-2) + 12px);
    background-image:
      linear-gradient(45deg, transparent 50%, currentColor 50%),
      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position:
      calc(100% - 12px) 50%,
      calc(100% - 7px) 50%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
  }
}

/* ---- Account: checkbox-style privacy fields ----
   The privacy form's existing fields are label + select stacked; these
   two are a checkbox inline with its label and the help text beneath,
   so they need their own arrangement rather than inheriting that. */
.privacy-form__field--check { display: block; margin-bottom: var(--space-4); }

.privacy-form__field--check > label {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  /* 44px target from the accessibility spec: the label is the hit
     area, not just the 16px box. */
  min-height: 44px;
  padding-block: var(--space-2);
  font-weight: var(--fw-semibold);
  color: var(--color-ink-heading);
  cursor: pointer;
}

.privacy-form__field--check input[type="checkbox"] {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.privacy-form__field--check .privacy-form__help {
  display: block;
  /* Aligned under the label text rather than the box. */
  padding-inline-start: calc(18px + var(--space-2));
}

.privacy-form__note {
  margin: 0 0 var(--space-4);
  padding: var(--space-3);
  border-inline-start: 3px solid var(--color-warning, #D97706);
  border-radius: var(--radius-sm);
  background: var(--color-bg-alt);
  font-size: var(--fs-sm);
  color: var(--color-ink-soft);
}

/* ===============================================================
   STICKY SIDEBARS — never overlap, never get clipped
   ===============================================================
   A sticky sidebar pins its TOP to the offset. When the sidebar is
   taller than the viewport, everything below the fold is unreachable:
   it neither scrolls with the page (it is pinned) nor scrolls itself
   (no height limit), so the lower cards read as sitting on top of the
   content beside them and cannot be scrolled to.

   Bounding the height to the visible space and letting the element
   scroll internally fixes it: a short sidebar behaves exactly as
   before, and a tall one becomes independently scrollable rather than
   truncated.

   align-self: start matters in grid parents — a stretched grid item is
   full-row height, and sticky never engages on an item as tall as its
   container.
   =============================================================== */
.article-sidebar,
.homepage-sidebar,
.taxonomy-filters,
.profile-tabs,
.page-rail {
  align-self: start;
  /* 64px header + a little breathing room, matching the top offsets
     these elements already use. */
  max-height: calc(100vh - 64px - var(--space-6));
  overflow-y: auto;
  /* Contain the scroll so reaching the sidebar's end does not start
     scrolling the page underneath mid-gesture. */
  overscroll-behavior: contain;
  /* The scrollbar only appears when it is needed; a permanently
     visible track on a short sidebar looks like breakage. */
  scrollbar-width: thin;
}

/* Below the two-column breakpoints these are in normal flow, where a
   height cap would crop content that has the full page width to use. */
@media (max-width: 1023px) {
  .article-sidebar,
  .homepage-sidebar,
  .taxonomy-filters,
  .profile-tabs,
  .page-rail {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

/* The Pulse rail is deliberately NOT sticky — it is a plain grid item
   in the page flow, so it scrolls with the feed and can never overlap
   it. Stated explicitly so a future global sidebar rule cannot make it
   sticky by accident. */
.pulse__rail {
  position: static;
  align-self: start;
  max-height: none;
  overflow: visible;
}

/* ===============================================================
   APP SIDEBAR — icon tiles and active state
   ===============================================================
   Each icon sits on its own tinted tile, and the active item is marked
   by a filled tile, a tinted row and a left rule — three signals, so
   the current page is still obvious in high-contrast mode and to a
   reader who cannot separate the hues.

   Done entirely in CSS: the icon is already a direct child of the
   link, so wrapping every item in a new element would have meant
   editing markup that four other templates also render.
   =============================================================== */

.app-nav-link {
  position: relative;
  gap: var(--space-3);
  padding-block: 6px;
}

/* The tile. A fixed box means labels line up in a column whether the
   glyph inside is wide or narrow. */
.app-nav-link > .icon {
  box-sizing: content-box;
  width: 18px;
  height: 18px;
  padding: 7px;
  border-radius: var(--radius-md);
  background: var(--color-bg-alt);
  color: var(--color-ink-soft);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.app-nav-link:hover > .icon {
  background: rgba(109, 94, 245, 0.10);
  color: var(--color-secondary-text);
}

/* ---- Active item ---- */
/* Plain rgba, deliberately — not color-mix().
   legacy-overrides.css also styles this, with color-mix() plus an
   @supports fallback, and this rule beats both wherever this sheet
   loads. That makes the build's cascade check report the fallback as
   unreachable, which it is: on these surfaces old browsers get this
   rgba instead, which they support. On public pages, where this sheet
   is not enqueued, the legacy fallback is reachable and does its job.
   So the warning is accurate and harmless — and the fix is NOT to
   swap this for color-mix(), which would leave older browsers with no
   background at all on every profile and Passport page. */
.app-nav-link.is-active {
  background: rgba(109, 94, 245, 0.08);
  color: var(--color-secondary-text);
  font-weight: var(--fw-semibold);
}

.app-nav-link.is-active > .icon {
  background: var(--color-secondary);
  color: #fff;
}

/* The left rule. An inset pseudo-element rather than a border, so the
   row's text never shifts by a pixel when it becomes active. */
.app-nav-link.is-active::before {
  content: '';
  position: absolute;
  inset-block: 6px;
  inset-inline-start: 0;
  width: 3px;
  border-radius: var(--radius-full);
  background: var(--color-secondary);
}

/* ---- Section heading ---- */
.app-sidebar__heading {
  font-size: 11px;
  font-weight: var(--fw-bold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-secondary-text);
}

/* ---- Counts ---- */
.app-nav-link__count {
  margin-inline-start: auto;
  min-width: 20px;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  color: #fff;
  font-size: 10px;
  font-weight: var(--fw-bold);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Dark mode: the tiles need their own surfaces, or a light tint on a
   dark rail reads as a rendering fault. */
html.jdev-dark .app-nav-link > .icon { background: rgba(255, 255, 255, 0.06); color: rgba(255, 255, 255, 0.72); }
html.jdev-dark .app-nav-link:hover > .icon { background: rgba(255, 255, 255, 0.12); color: #fff; }
html.jdev-dark .app-nav-link.is-active { background: rgba(109, 94, 245, 0.22); }
html.jdev-dark .app-nav-link.is-active > .icon { background: var(--color-secondary); color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .app-nav-link > .icon { transition: none; }
}
