/* The card link panel (member profile) and the install block the portal shares.
   ---------------------------------------------------------------------------

   Two small surfaces with one job: a member must be able to find their card
   again after the launch day. The panel is the link itself -- shown large enough
   to read off a screen, copyable, scannable and shareable -- and the install
   block is the standing invitation to keep it on the phone's home screen.

   Both are drawn in the profile editor's language (public/assets/css/portal-profile.css):
   white cards, 14px corners, a 13px label voice and the member's own accent. The
   tokens below are re-declared with the same fallbacks the editor uses, because
   the layout loads this sheet on every portal page and only the editor loads the
   editor's own sheet. Nothing here sets a font-family: the panel inherits the
   page it is on, which is CircularStd in the editor and the system stack on the
   entry and code screens. */

.card-link,
.install-app {
    --card-link-ink: var(--pp-ink, #1F2A3D);
    --card-link-muted: var(--pp-muted, #667085);
    --card-link-border: var(--pp-border, #DEE5EE);
    --card-link-surface: var(--pp-surface, #F5F8FC);
    --card-link-chip: var(--pp-chip, #EAF0F8);
    --card-link-accent: var(--brand-color, #087b48);
    --card-link-accent-wash: var(--pp-accent-wash, #F1F7F3);
    --card-link-accent-line: var(--pp-accent-line, #CBE0D3);
    /* The accent mixed toward the dark ink, so a pale brand choice still holds a
       white label: the same rule the editor's primary button follows. */
    --card-link-accent-deep: #142b25;
}

/* The controls above are revealed by script. A class that sets a display wins
   over the UA's own [hidden] rule, so the attribute is restated with the weight
   the state needs, on the element and on anything inside it. */
.card-link[hidden],
.install-app[hidden],
.card-link [hidden],
.install-app [hidden],
.card-dismiss__menu[hidden] {
    display: none !important;
}

/* The two ways of putting a card away. This is the state the layout's boot
   writes before first paint from localStorage, so a card hid for good never
   flashes while the script below is still loading. */
html.is-dismissed-card-link [data-dismissible="card-link"],
html.is-dismissed-install-app [data-dismissible="install-app"] {
    display: none !important;
}

/* ----------------------------------------------------------------- card link */

.card-link {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 20px 24px;
    /* The scan is centred against the link it encodes: the two columns come out
       close in height, and centring splits the difference instead of leaving all
       of it under the buttons. */
    align-items: center;
    padding: 22px 24px;
    margin-bottom: 20px;
    background: #fff;
    border: 1px solid var(--card-link-border);
    border-radius: 14px;
    color: var(--card-link-ink);
}

.card-link__head {
    display: flex;
    grid-column: 1 / -1;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

/* The title and its sentence stay one block: the close control is the header's
   second child, not a third line in the copy. */
.card-link__intro {
    min-width: 0;
}

.card-link__title {
    margin: 0 0 4px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
}

.card-link__lede,
.card-link__empty {
    margin: 0;
    color: var(--card-link-muted);
    font-size: 13px;
    line-height: 1.55;
}

/* The address owns a line of its own and the controls that act on it share the
   row under it, so this is one wrapping flow rather than a stack of blocks: a
   button can move to the next line on its own when the space is not there. */
.card-link__details {
    display: flex;
    flex-wrap: wrap;
    column-gap: 10px;
    min-width: 0;
}

/* Boxes only where they do something: the field and the action row are the two
   groups a phone lays out differently (see the responsive block), and on every
   wider screen they are transparent to the flow above. */
.card-link__field,
.card-link__actions {
    display: contents;
}

.card-link__label {
    flex: 0 0 100%;
    margin: 0 0 8px;
    color: var(--card-link-muted);
    font-size: 12px;
    font-weight: 500;
}

/* The link is the one thing this panel exists for, so it is the loudest object
   on it: monospaced to make the 7-character code legible, selectable as a whole
   for a browser without script, and wrapped rather than clipped on a phone. */
.card-link__url {
    display: block;
    flex: 0 0 100%;
    padding: 12px 14px;
    border: 1px solid var(--card-link-accent-line);
    border-radius: 10px;
    background: var(--card-link-accent-wash);
    color: var(--card-link-ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 14px;
    line-height: 1.45;
    text-decoration: none;
    user-select: all;
    word-break: break-all;
}

.card-link__url:hover,
.card-link__url:focus-visible {
    border-color: var(--card-link-accent);
    text-decoration: underline;
}

.card-link__url:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

.card-link__button,
.install-app__button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 10px 16px;
    border: 1px solid #C9D5E4;
    border-radius: 7px;
    background: #fff;
    color: var(--card-link-ink);
    font: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 20px;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}

.card-link__button:hover,
.install-app__button:hover {
    border-color: var(--card-link-accent);
    background: var(--card-link-chip);
    color: var(--card-link-ink);
    text-decoration: none;
}

.card-link__button--primary,
.install-app__button {
    border-color: transparent;
    background: var(--card-link-accent-deep);
    background: color-mix(in srgb, var(--card-link-accent) 35%, #142b25);
    color: #fff;
}

.card-link__button--primary:hover,
.install-app__button:hover {
    border-color: transparent;
    background: var(--card-link-accent-deep);
    color: #fff;
}

/* The controls begin one gap under the address. The actions wrapper no longer
   makes that row (it is transparent here), so the gap lives on the controls. */
.card-link__button {
    margin-top: 14px;
}

/* One ring for both buttons: the accent ring disappears into the primary fill,
   while this one holds against the white cards and against the brand colour. */
.card-link__button:focus-visible,
.install-app__button:focus-visible,
.install-app__help-summary:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

/* The copy confirmation. Empty until the browser has something to say, so it
   takes no room in a panel that has not been used yet; aria-live on the element
   is what makes the sentence reach a screen reader. */
.card-link__status {
    flex: 0 0 100%;
    margin: 10px 0 0;
    color: var(--card-link-accent);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.5;
}

.card-link__status:empty {
    display: none;
}

/* Scan-to-open: the card's own corner, in the accent wash behind a white well,
   so the QR reads as the printed card rather than as one more grey box. What is
   drawn here is the picture; the enlarged copy lives in the dialog below. */
.card-link__scan {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px 12px 9px;
    border: 1px solid var(--card-link-border);
    border-radius: 12px;
    background: var(--card-link-surface);
}

.card-link__scan-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

/* Laid over the code without a box of its own: the picture underneath stays the
   drawing, and the corner mark is all this control adds. card-link.js reveals
   it, along with the dialog it opens. */
.card-link__scan-open {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    padding: 6px;
    border: 0;
    border-radius: 12px;
    background: transparent;
    color: var(--card-link-muted);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.card-link__scan-open:hover {
    color: var(--card-link-ink);
    background: color-mix(in srgb, var(--card-link-accent) 6%, transparent);
}

.card-link__scan-open:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

.card-link__qr {
    width: 132px;
    padding: 7px;
    border-radius: 9px;
    background: #fff;
}

.card-link__qr svg {
    display: block;
    width: 100%;
    height: auto;
}

.card-link__scan-note {
    margin: 0;
    color: var(--card-link-muted);
    font-size: 11.5px;
    line-height: 1.4;
}

/* --------------------------------------------------------------- qr dialog */

/* The code at full size, laid over the page the way the card's own QR dialog is.
   Drawn in the panel's language rather than in the card's: the member is still
   in the editor here, and a card-themed sheet would read as a different screen.
   Opened by card-link.js only, which is why it starts hidden. */
.card-link-modal {
    position: fixed;
    inset: 0;
    z-index: 1080;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.card-link-modal.is-open {
    display: flex;
}

/* The page behind a dialog is held still: the member scrolls the dialog, not the
   editor under it. */
body.card-link-modal-open {
    overflow: hidden;
}

.card-link-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.62);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

.card-link-modal__dialog {
    position: relative;
    z-index: 2;
    width: min(340px, 100%);
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    padding: 22px 22px 24px;
    border: 1px solid var(--card-link-border);
    border-radius: 14px;
    background: #fff;
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.3);
    text-align: center;
}

/* The dialog takes focus when it opens, so the title and the sentence are what
   a screen reader reads first. No ring is drawn on the sheet itself: it is a
   container, not a control, and the ring belongs on the button inside it. */
.card-link-modal__dialog:focus {
    outline: none;
}

.card-link-modal__close {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 50%;
    background: var(--card-link-chip);
    color: var(--card-link-ink);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.card-link-modal__close:hover {
    background: var(--card-link-ink);
    color: #fff;
}

.card-link-modal__close:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

.card-link-modal__title {
    margin: 4px 34px 6px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
}

.card-link-modal__lede {
    margin: 0 auto 16px;
    max-width: 32ch;
    color: var(--card-link-muted);
    font-size: 12.5px;
    line-height: 1.55;
}

/* The code keeps the panel's accent frame around a white well: the dialog is the
   paper the member hands over, so the code sits on white rather than on a wash. */
.card-link-modal__qr {
    width: min(220px, 62vw);
    margin: 0 auto;
    padding: 10px;
    border: 1px solid var(--card-link-accent-line);
    border-radius: 12px;
    background: #fff;
}

.card-link-modal__qr svg {
    display: block;
    width: 100%;
    height: auto;
}

/* ---------------------------------------------------------------- install app */

/* A quiet strip rather than a second card: the copy on the left, the controls it
   offers on the right, and one line under them for the member who would rather
   bookmark. The accent lives in the title's rule and the primary button, not in
   a wash over the whole block. */
.install-app {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    /* The title owns a row of its own so the close control does not land on the
       install buttons; the copy and the buttons share the row under it. */
    gap: 6px 24px;
    align-items: start;
    /* Room to breathe above and below: the cards nearby and the page's footer
       must not read as part of this one. Adjacent vertical margins collapse, so
       a card that already sets its own bottom margin does not double it. */
    padding: 22px 24px;
    margin: 24px 0;
    background: #fff;
    border: 1px solid var(--card-link-border);
    border-radius: 14px;
    color: var(--card-link-ink);
}

.install-app__head {
    display: flex;
    grid-column: 1 / -1;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.install-app__title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.35;
}

.install-app__title::before {
    content: '';
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 9px;
    border-radius: 2px;
    background: var(--card-link-accent);
    vertical-align: 2px;
}

.install-app__lede {
    margin: 0;
    max-width: 46ch;
    color: var(--card-link-muted);
    font-size: 13px;
    line-height: 1.55;
}

.install-app__hint {
    margin: 8px 0 0;
    color: var(--card-link-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.install-app__actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    min-width: 250px;
}

.install-app__help {
    border: 1px solid var(--card-link-border);
    border-radius: 9px;
    background: #fff;
}

.install-app__help[open] {
    background: var(--card-link-surface);
}

/* A control, not a disclosure triangle floating in the paragraph: the summary is
   the button-shaped affordance for every browser that has no install prompt. */
.install-app__help-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    /* A 44px row: the summary is the one control here on a phone that cannot
       be prompted, so it is sized as a touch target rather than a line. */
    min-height: 44px;
    padding: 10px 14px;
    color: var(--card-link-ink);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    list-style: none;
}

.install-app__help-summary::-webkit-details-marker {
    display: none;
}

.install-app__help-summary::after {
    content: '';
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    margin-right: 3px;
    border-right: 1.5px solid var(--card-link-muted);
    border-bottom: 1.5px solid var(--card-link-muted);
    transform: rotate(45deg) translateY(-1px);
    transition: transform .15s ease;
}

.install-app__help[open] .install-app__help-summary::after {
    transform: rotate(225deg) translateY(-1px);
}

/* The platform chooser: two rows, each the whole label, so the radio the
   browser draws is the one the member taps. install.js reveals it; until then
   the rows below are a plain list and both sets of steps stay in the page. */
.install-app__help-pick {
    display: grid;
    gap: 4px;
    margin: 0;
    padding: 0 10px 6px;
    border: 0;
}

.install-app__help-option {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    /* Bootstrap gives every label a bottom margin; these rows are controls,
       and their spacing comes from the grid gap. */
    margin: 0;
    padding: 8px 10px;
    border-radius: 8px;
    color: var(--card-link-ink);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    transition: background-color .15s ease;
}

.install-app__help-option:hover {
    background: var(--card-link-chip);
}

/* The chosen platform is the one whose steps are showing. The row keeps the
   neutral chip -- the accent wash belongs to the editor's own sheet, which
   this block also renders without -- and the ticked radio carries the colour. */
.install-app__help-option:has(input:checked) {
    background: var(--card-link-chip);
}

.install-app__help-option input:checked + span {
    font-weight: 600;
}

.install-app__help-option input {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--card-link-accent);
    cursor: pointer;
}

.install-app__help-option input:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

/* With the chooser in the page the round list markers would read as a second
   set of radios, so the steps below lose them and line up as paragraphs. The
   platform heading goes too once a row is picked: the ticked row already says
   which phone the sentence is for. */
.install-app__help-pick:not([hidden]) ~ .install-app__help-list {
    list-style: none;
}

.install-app__help-pick:has(input:checked) ~ .install-app__help-list strong {
    display: none;
}

.install-app__help-list {
    margin: 0;
    padding: 0 14px 14px;
    color: var(--card-link-muted);
    font-size: 12.5px;
    line-height: 1.55;
}

.install-app__help-list li:not([hidden]) + li:not([hidden]) {
    margin-top: 10px;
}

.install-app__help-list strong {
    display: block;
    color: var(--card-link-ink);
    font-weight: 600;
}

.install-app__status {
    margin: 0;
    color: var(--card-link-accent);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.5;
}

.install-app__status:empty {
    display: none;
}

/* ---------------------------------------------------------------- dismiss */

/* One control shared by both cards. It sits at the end of the card's header, not
   over its content: the card link's code and the install block's buttons each
   keep the spot they already had. The button is switched on by card-dismiss.js,
   which is also what stops a browser without script from being offered a close
   that cannot close. */
.card-dismiss {
    position: relative;
    flex: 0 0 auto;
}

.card-dismiss__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 50%;
    background: transparent;
    color: var(--card-link-muted);
    font: inherit;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.card-dismiss__toggle:hover {
    background: var(--card-link-chip);
    color: var(--card-link-ink);
}

.card-dismiss__toggle:focus {
    outline: none;
}

.card-dismiss__toggle:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: 2px;
}

/* The menu opens under the button and over the card: it is a question about
   the card, not a new row in it, so the card does not reflow while it is up. */
.card-dismiss__menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 40;
    width: 16rem;
    max-width: calc(100vw - 32px);
    padding: 6px;
    border: 1px solid var(--card-link-border);
    border-radius: 12px;
    background: #fff;
    box-shadow:
        0 22px 48px -24px rgba(15, 23, 42, .45),
        0 2px 6px rgba(15, 23, 42, .07);
    text-align: left;
}

.card-dismiss__question {
    margin: 4px 8px 6px;
    color: var(--card-link-ink);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.4;
}

/* Each choice is its label and the sentence that says what it will do. The
   two-line row is the point: "hide forever" is only fair if the difference is
   visible before it is chosen. */
.card-dismiss__option {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color .15s ease;
}

.card-dismiss__option span {
    color: var(--card-link-ink);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.4;
}

.card-dismiss__option small {
    color: var(--card-link-muted);
    font-size: 11.5px;
    line-height: 1.45;
}

.card-dismiss__option:hover,
.card-dismiss__option:focus {
    background: var(--card-link-chip);
}

/* Opening the menu moves focus to the first choice, so the row is highlighted
   even on a touch screen. The ring itself is keyboard-only: Bootstrap's own
   button:focus ring is the browser-blue one, and a tap does not need a ring. */
.card-dismiss__option:focus {
    outline: none;
}

.card-dismiss__option:focus-visible {
    outline: 3px solid #1F2A3D;
    outline-offset: -3px;
}

/* The confirmation for a hidden card, appended to the body by the script. It is
   visually gone but stays a live region, so a screen reader hears which way the
   member hid it. */
.card-dismiss__status {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    border: 0;
    white-space: nowrap;
}

/* The landmark that takes focus when the card holding it is gone. It is not in
   the tab order, so the ring would only ever be a programmatic artifact. */
.card-dismiss-focus:focus {
    outline: none;
}

/* Installed already: the block has nothing left to offer, and this holds for a
   browser without script too, which is the case this rule is really for. */
@media all and (display-mode: standalone) {
    .install-app {
        display: none;
    }
}

/* ---------------------------------------------------------------- responsive */

@media (max-width: 767.98px) {
    .install-app {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 16px;
        padding: 22px 20px;
    }

    .install-app__actions {
        min-width: 0;
    }
}

@media (max-width: 575.98px) {
    /* The panel is the first thing under the identity card on every tab, so on a
       phone it is packed tighter: the address and the copy control become one
       field, the two quiet controls share the row under it, and the code gets a
       strip of its own instead of a card floating in half the column. */
    .card-link {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px 0;
        padding: 16px;
    }

    .card-link__details {
        display: block;
    }

    /* One field, with the copy control as its right-hand key. The key is as tall
       as the address beside it -- two lines on most phones -- so the two read as
       a single object rather than a link with a button parked next to it. */
    .card-link__field {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: stretch;
        border: 1px solid var(--card-link-accent-line);
        border-radius: 10px;
        background: var(--card-link-accent-wash);
    }

    .card-link__url {
        padding: 11px 12px 11px 14px;
        border: 0;
        border-radius: 10px 0 0 10px;
        background: transparent;
        font-size: 13px;
    }

    /* The border belongs to the field now, so the ring goes just inside it: an
       outer one would sit on top of that border. */
    .card-link__url:focus-visible {
        outline-offset: -3px;
    }

    /* The key is the icon alone; the word it hides is still the control's
       accessible name, so it is only the drawing that has gone. */
    [data-card-link-copy] {
        min-width: 48px;
        gap: 0;
        margin-top: 0;
        padding: 0;
        border-radius: 0 9px 9px 0;
    }

    [data-card-link-copy] span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    [data-card-link-copy]:focus-visible {
        outline-offset: -4px;
        outline-color: #fff;
    }

    .card-link__button {
        margin-top: 0;
    }

    .card-link__actions {
        display: flex;
        flex-wrap: wrap;
        gap: 10px;
        margin-top: 10px;
    }

    /* Under the controls on a phone the code takes the full column: the code and
       its caption centred together, rather than a card in half the width with
       the rest of the row left empty. */
    .card-link__scan {
        justify-content: center;
        width: 100%;
        padding: 12px;
    }

    .card-link__scan-preview {
        flex-direction: row;
        gap: 14px;
    }

    .card-link__qr {
        width: 76px;
        padding: 6px;
    }

    .card-link__button,
    .install-app__button {
        flex: 1 1 auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .card-link__button,
    .install-app__button,
    .install-app__help-option,
    .install-app__help-summary::after,
    .card-link__scan-open,
    .card-link-modal__close,
    .card-dismiss__toggle,
    .card-dismiss__option {
        transition: none;
    }
}
