/* Profile Sync Core — client surfaces (EP0018 / US0096): owner management, field-mapping admin, visualiser. */

.ps-owner,
.ps-form-mapping,
.ps-visualiser {
	margin: 1em 0;
	font-size: 14px;
}

.ps-owner__title,
.ps-form-mapping__title,
.ps-visualiser__title {
	margin: 0 0 0.5em;
	font-size: 1.1em;
}

/* Tables (members / mappings) */
.ps-owner__members,
.ps-form-mapping__list {
	width: 100%;
	border-collapse: collapse;
}

.ps-owner__members th,
.ps-owner__members td,
.ps-form-mapping__list th,
.ps-form-mapping__list td {
	padding: 6px 8px;
	border-bottom: 1px solid #e2e6ea;
	text-align: left;
}

.ps-owner__empty,
.ps-form-mapping__empty,
.ps-owner__pending .ps-owner__empty {
	color: #6b7680;
	font-style: italic;
}

/* Action buttons */
.ps-owner__action,
.ps-form-mapping__delete {
	cursor: pointer;
	padding: 3px 10px;
	border: 1px solid #c3ccd4;
	border-radius: 3px;
	background: #f6f8fa;
}

.ps-owner__action:hover,
.ps-form-mapping__delete:hover {
	background: #eceff2;
}

/* CR-0181: per-member role editor in the owner console. */
.ps-owner__role-editor {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.35em 0.75em;
}

.ps-owner__role {
	display: inline-flex;
	align-items: center;
	gap: 0.25em;
	white-space: nowrap;
}

.ps-owner__roles-save {
	cursor: pointer;
	padding: 3px 10px;
	border: 1px solid #c3ccd4;
	border-radius: 3px;
	background: #f6f8fa;
}

.ps-owner__roles-save:hover {
	background: #eceff2;
}

.ps-owner__roles-msg {
	color: #6b7680;
	font-size: 0.92em;
}

/* CR-0183: owner console restyled to the manager surface. */
.ps-owner__head {
	display: flex;
	align-items: center;
	gap: 0.75em;
	margin: 0 0 0.75em;
	padding: 0.5em 0.75em;
	background: #eff6ff; /* light blue */
	border: 1px solid #dbeafe;
	border-radius: 6px;
}

.ps-owner__head .ps-owner__title {
	margin: 0;
	font-size: 1.35em;
	line-height: 1.2;
}

/* Fixed-height logo box next to the heading — matches the heading height, keeps aspect ratio. */
.ps-owner__logo {
	flex: 0 0 auto;
	align-self: stretch;
	display: flex;
	align-items: center;
	max-width: 96px;
}

.ps-owner__logo img {
	height: 100%;
	width: auto;
	max-height: 2.4em;
	max-width: 96px;
	object-fit: contain;
	display: block;
}

/* Sortable headers */
.ps-owner__sort {
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	font: inherit;
	font-weight: 600;
	cursor: pointer;
	color: inherit;
}

.ps-owner__members th[aria-sort="ascending"] .ps-owner__sort::after { content: " \25B2"; }
.ps-owner__members th[aria-sort="descending"] .ps-owner__sort::after { content: " \25BC"; }

/* Role pills (display) */
.ps-owner__role-pill {
	display: inline-block;
	padding: 1px 9px;
	margin: 1px 3px 1px 0;
	border-radius: 25px;
	background: #eef2f7;
	border: 1px solid #d6dde3;
	font-size: 0.9em;
	white-space: nowrap;
}

.ps-owner__role-none,
.ps-owner__email-none {
	color: #9aa4ad;
}

/* Actions cell + the role-editor popover */
.ps-owner__actions-inner {
	display: flex;
	align-items: flex-start;
	gap: 0.4em;
	position: relative;
}

.ps-owner__role-pop {
	position: absolute;
	top: 100%;
	right: 0;
	z-index: 20;
	margin-top: 4px;
	padding: 0.6em 0.75em;
	min-width: 12em;
	background: #fff;
	border: 1px solid #c3ccd4;
	border-radius: 6px;
	box-shadow: 0 6px 20px rgba( 0, 0, 0, 0.12 );
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 0.5em;
}

/* A [hidden] popover must stay hidden despite the display rule above (attribute vs class specificity). */
.ps-owner__role-pop[hidden],
.ps-owner__tier-pop[hidden] {
	display: none;
}

/* Stack the role checkboxes so their boxes align down the left edge. */
.ps-owner__role-list {
	display: flex;
	flex-direction: column;
	gap: 0.3em;
}

.ps-owner__role {
	display: flex;
	align-items: center;
	gap: 0.4em;
	white-space: nowrap;
}

.ps-owner__role--none {
	margin-top: 0.15em;
	padding-top: 0.35em;
	border-top: 1px solid #eef2f7;
	color: #6b7680;
}

/* Centre the Save button under the stacked roles. */
.ps-owner__role-actions {
	text-align: center;
}

/* CR-0185: over-limit, floor-lock, tier pill in the head, red overflow. */
.ps-owner__seats-num--over {
	color: #dc2626;
	font-weight: 700;
}

/* An over-limit member (surplus beyond the tier cap) is greyed — their seat is inactive. */
.ps-owner__member-row--over .ps-owner__user,
.ps-owner__member-row--over .ps-owner__email,
.ps-owner__member-row--over .ps-owner__roles {
	opacity: 0.5;
}

/* Disabled action buttons (floor-locked member) read as unavailable. */
.ps-owner__actions-inner .ps-btn:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.ps-owner__role-lock {
	margin-left: 0.25em;
	cursor: help;
}

.ps-owner__head-tier {
	margin-left: 0.5em;
}

.ps-owner__tier-arrow {
	margin: 0 0.15em;
	color: #6b7680;
}

/* CR-0183 Inc 2: seat line + tier-upgrade request popover. */
.ps-owner__seats {
	position: relative; /* anchors the absolutely-positioned upgrade popover */
	margin: 0.5em 0 0.75em;
	color: #374151;
}

.ps-owner__tier-open {
	background: none;
	border: 0;
	padding: 0;
	font: inherit;
	color: #2563eb;
	text-decoration: underline;
	cursor: pointer;
}

.ps-owner__tier-pop {
	position: absolute;
	top: 1.9em;
	left: 0;
	z-index: 20;
	min-width: 16em;
	padding: 0.75em 0.85em;
	background: #fff;
	border: 1px solid #c3ccd4;
	border-radius: 6px;
	box-shadow: 0 6px 20px rgba( 0, 0, 0, 0.12 );
}

.ps-owner__tier-label {
	display: block;
}

.ps-owner__tier-select {
	max-width: 100%;
	margin-top: 0.35em;
	padding: 3px 6px;
	font-size: 0.95em;
}

.ps-owner__tier-cost {
	margin: 0.5em 0;
	color: #6b7680;
	font-size: 0.92em;
}

.ps-owner__tier-ack-label {
	display: block;
	margin: 0.35em 0 0.6em;
}

.ps-owner__tier-status {
	margin-left: 0.5em;
	color: #6b7680;
	font-size: 0.92em;
}

/* CR-0183 Inc 3: Invitations section + "New invitation" popover. */
.ps-owner__invitations {
	margin-top: 1em;
}

.ps-owner__invitations-title {
	margin: 0 0 0.4em;
}

.ps-owner__invite-new {
	position: relative;
	margin-top: 0.6em;
}

.ps-owner__invite-pop {
	position: absolute;
	top: 2.4em;
	left: 0;
	z-index: 20;
	min-width: 18em;
	padding: 0.85em 0.95em;
	background: #fff;
	border: 1px solid #c3ccd4;
	border-radius: 6px;
	box-shadow: 0 6px 20px rgba( 0, 0, 0, 0.12 );
}

.ps-owner__invite-pop[hidden] {
	display: none;
}

.ps-owner__invite-field {
	display: block;
	margin: 0 0 0.5em;
}
/* BG0097: when the template lacks {email_insert}, owner-management.js sets [hidden] on the Message field to degrade
   insert→show — but the display:block above would override the UA [hidden] rule (author beats user-agent), leaving the
   box visible. Force it hidden (also covers the edit body field). */
.ps-owner__invite-field[hidden] {
	display: none;
}

.ps-owner__invite-field input,
.ps-owner__invite-field select {
	display: block;
	width: 100%;
	margin-top: 0.2em;
	padding: 3px 6px;
	box-sizing: border-box;
}

.ps-owner__invite-actions {
	margin-top: 0.6em;
}

.ps-owner__invite-status {
	margin-left: 0.5em;
	color: #6b7680;
	font-size: 0.92em;
}

/* CR-0225: the invite email message box (insert) + its counter, and the live formatted preview (show/insert). */
.ps-owner__invite-message textarea {
	display: block;
	width: 100%;
	margin-top: 0.25em;
	font: inherit;
}
.ps-owner__invite-counter {
	display: block;
	margin-top: 0.2em;
	color: #6b7680;
	font-size: 0.85em;
}
.ps-owner__invite-editbody textarea {
	display: block;
	width: 100%;
	margin-top: 0.25em;
	font: inherit;
	min-height: 10em;
}
.ps-owner__invite-preview {
	margin-top: 0.8em;
	border: 1px solid #d5dbe0;
	border-radius: 6px;
	overflow: hidden;
	background: #fff;
}
.ps-owner__invite-preview[hidden] {
	display: none;
}
.ps-owner__invite-preview-frame {
	display: block;
	width: 100%;
	height: 320px;
	border: 0;
}

.ps-owner__invite-full {
	margin: 0.6em 0 0;
	color: #92400e;
	font-style: italic;
}

/* Forms */
.ps-form-mapping__save {
	margin-top: 0.75em;
}

.ps-form-mapping__field {
	margin: 0.5em 0;
}

.ps-form-mapping__fields,
.ps-form-mapping__meta {
	margin: 1em 0;
	padding: 0.5em 0.75em;
	border: 1px solid #d6dde3;
	border-radius: 4px;
}

.ps-form-mapping__fields legend,
.ps-form-mapping__meta legend {
	font-weight: 600;
	padding: 0 0.35em;
}

.ps-form-mapping__help {
	margin: 0 0 0.5em;
	color: #6b7680;
	font-size: 0.92em;
}

.ps-fm-table {
	width: 100%;
	border-collapse: collapse;
}

.ps-fm-table th {
	text-align: left;
	font-size: 0.85em;
	color: #6b7680;
	padding: 0.2em 0.4em;
}

.ps-fm-table td {
	padding: 0.2em 0.4em;
}

.ps-fm-table input,
.ps-fm-table select {
	width: 100%;
}

.ps-fm-remove {
	border: 0;
	background: none;
	color: #b3261e;
	font-size: 1.1em;
	cursor: pointer;
	line-height: 1;
}

.ps-fm-add-row {
	margin-top: 0.5em;
}

/* Visualiser canvas */
.ps-visualiser__canvas {
	width: 100%;
	height: 520px;
	border: 1px solid #d6dde3;
	border-radius: 4px;
	background: #fbfcfd;
	position: relative;
}

.ps-visualiser__fallback {
	padding: 1em;
	color: #6b7680;
	font-style: italic;
}

.ps-visualiser__save {
	margin-top: 8px;
}

/* Visualiser legend (VZ / RV0005) — mirrors the edge styling in visualiser.js */
.ps-visualiser__legend {
	list-style: none;
	margin: 8px 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 16px;
	font-size: 12px;
	color: #3a4d5e;
}
.ps-visualiser__legend li {
	display: flex;
	align-items: center;
	gap: 6px;
}
.ps-visualiser__swatch {
	display: inline-block;
	width: 24px;
	height: 0;
	border-top-width: 3px;
	border-top-style: solid;
}
.ps-visualiser__swatch--mapping { border-top-color: #2563eb; }
.ps-visualiser__swatch--schema { border-top-style: dashed; border-top-color: #d97706; }
.ps-visualiser__swatch--form { border-top-style: dashed; border-top-color: #0d9488; }
/* CR-0029 inc 4: topology cues — loop-closing edge (the minimal cut) + healed/paused mapping. */
.ps-visualiser__swatch--loop { border-top-width: 4px; border-top-color: #dc2626; }
.ps-visualiser__swatch--paused { border-top-style: dashed; border-top-color: #9ca3af; }

/* Visualiser toolbar (VZ01) */
.ps-visualiser__toolbar {
	margin-top: 8px;
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.ps-owner--error,
.ps-owner--denied,
.ps-form-mapping--error,
.ps-form-mapping--denied,
.ps-visualiser--error {
	padding: 0.75em 1em;
	border-left: 3px solid #d3a85b;
	background: #fff7ec;
}

/* BG0043 / CR-0020 inc2c: the guided migrate-role modal (front-end members panel). */
.ps-migrate-overlay {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	padding: 5vh 1rem;
	background: rgba( 15, 23, 42, .55 );
	overflow: auto;
}
.ps-migrate-dialog {
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 10px 40px rgba( 0, 0, 0, .25 );
	width: 460px;
	max-width: 100%;
	padding: 1.25rem 1.5rem;
}
.ps-migrate-recipient { width: 100%; margin: .5rem 0; }
.ps-migrate-actions { margin-top: 1rem; display: flex; gap: .5rem; align-items: center; }

/* CR-0120 Inc 3: the application "Summary" popup — each field's label sits ABOVE its value (both full-width) so a long
   question/label never squeezes the value into a sliver. The dialog is a touch wider and scrolls when there are many
   fields. */
.ps-summary-dialog { width: 560px; max-height: 80vh; overflow-y: auto; }
.ps-summary-list { margin: .5rem 0 0; }
/* CR-0345: the snapshot header + the full submission below the ticked summary. The dialog already scrolls
   (max-height + overflow-y above), so a long application stays inside the popup rather than growing off-screen. */
.ps-summary-meta { margin: 0 0 .5rem; color: #475569; font-size: .9em; }
.ps-summary-meta small { color: #64748b; }
/* CR-0390: the waiting line reads as a FACT ABOUT THE PERSON, not more document metadata — the operator scans for it
   to decide whether somebody has been stuck too long, so it carries its own weight rather than blending into the grey. */
.ps-summary-meta .ps-summary-waiting { color: #1e293b; font-weight: 600; }
.ps-summary-detail { margin-top: 1.1rem; border-top: 1px solid #e2e8f0; padding-top: .75rem; }
.ps-summary-detail h4 { margin: 0; font-size: 1em; color: #1e293b; }
.ps-summary-detail h5 { margin: .9rem 0 0; font-size: .85em; text-transform: uppercase; letter-spacing: .04em; color: #64748b; }
.ps-summary-list dt { font-weight: 600; color: #1e293b; margin-top: .85rem; }
.ps-summary-list dt:first-child { margin-top: 0; }
.ps-summary-list dd { margin: .15rem 0 0; color: #334155; overflow-wrap: anywhere; }
.ps-summary-empty { margin: .5rem 0 0; color: #64748b; }

/* CR-0334: the manager contact-card trigger. It must be a real <button> for keyboard reach, so every default button
   style is unwound back to inline text — otherwise a member's name renders as a grey WordPress button in the middle
   of a table cell. It reads as a link (the affordance managers already know) without being one, since there is no
   URL to follow: the details open in place. */
.ps-contact-card-trigger {
	background: none; border: 0; padding: 0; margin: 0; font: inherit; line-height: inherit; text-align: left;
	color: #2271b1; cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.ps-contact-card-trigger:hover, .ps-contact-card-trigger:focus { color: #135e96; }
.ps-contact-card-dialog .ps-contact-card-crm { margin: 1rem 0 0; }
/* BG0196: a configured-but-empty field. Muted and italic so the card still reads as a list of what IS known at a
   glance, while the empty rows stay present and countable — the point being that the manager can see the field was
   asked for and nobody has answered it. */
.ps-contact-card-dialog .ps-contact-card-empty { color: #787c82; font-style: italic; }

/* CR-0124 Inc 1a: the guided Approve modal — a read-only org line + a tier picker. */
.ps-approve-org { margin: .25rem 0 .75rem; color: #475569; }
/* CR-0131 Inc 2: the org "Add member" picker (associated users) in the expandable Members list. */
.ps-org-add-member { margin: .5rem 0 .25rem; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.ps-org-add-member-label { font-size: .9em; }
.ps-org-add-member-msg { color: #b32d2e; font-size: .85em; }
/* CR-0132 Inc 2: the "missing a required role" warning above the add-member picker. */
.ps-org-add-member-required { color: #b32d2e; font-weight: 600; margin: .25rem 0; }
/* CR-0133: a multi-role membership offers checkbox roles (add several at once) instead of a single <select>. */
.ps-org-add-member-roles { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .1rem .6rem; }
.ps-org-add-member-role-opt { display: inline-flex; align-items: center; gap: .2rem; font-size: .9em; }
/* CR-0127 Inc 2: the floor-locked role indicator (e.g. the last Admin can't be changed). */
.ps-role-locked { cursor: help; font-size: .95em; opacity: .8; }
.ps-role-locked:focus { outline: 2px solid #2271b1; outline-offset: 2px; }
/* CR-0126 Inc 2: the expandable per-organisation members (user) list. */
.ps-org-members-toggle { background: none; border: 0; padding: 0; color: #2271b1; cursor: pointer; font: inherit; text-decoration: underline; }
.ps-org-members-detail > td { background: #f8fafc; padding: .5rem .75rem; }
.ps-org-members-users { width: 100%; margin: 0; }
.ps-org-members-users th { font-size: .82em; text-transform: uppercase; color: #64748b; }
/* CR-0200 follow-up: the members table and the Parked table share this class but auto-sized their columns
   independently (content-driven), so the two grids drifted apart. A FIXED layout with explicit header widths
   makes every column line up exactly across both tables: Name | Email | Role | Other memberships | Actions. */
.ps-org-members-users { table-layout: fixed; }
/* BG0171: these are POSITIONAL and describe the FIVE-column grid (Name · Email · Role · Other memberships ·
   Actions) shared by the invitations and parked tables. They are scoped with `:not(.ps-has-admin-email)` because the
   members table grows a SIXTH column when the admin-email toggle is on: unscoped, `nth-child(4)`'s 23% landed on the
   checkbox column, `nth-child(5)`'s 16% on Other memberships, and Actions matched nothing at all — which under
   `table-layout: fixed` collapses it and overlaps the headers. */
.ps-org-members-users:not(.ps-has-admin-email) th:nth-child(1) { width: 20%; }
.ps-org-members-users:not(.ps-has-admin-email) th:nth-child(2) { width: 28%; }
.ps-org-members-users:not(.ps-has-admin-email) th:nth-child(3) { width: 13%; }
.ps-org-members-users:not(.ps-has-admin-email) th:nth-child(4) { width: 23%; }
.ps-org-members-users:not(.ps-has-admin-email) th:nth-child(5) { width: 16%; }
/* The SIX-column grid: Name · Email · Role · Receive admin emails · Other memberships · Actions. The checkbox column
   takes the smallest slice that still fits the stacked header; the rest is redistributed rather than borrowed from
   Actions, which is what collapsed before. Sums to 100% so `fixed` has nothing to invent. */
.ps-org-members-users.ps-has-admin-email th:nth-child(1) { width: 20%; }
.ps-org-members-users.ps-has-admin-email th:nth-child(2) { width: 26%; }
.ps-org-members-users.ps-has-admin-email th:nth-child(3) { width: 12%; }
.ps-org-members-users.ps-has-admin-email th:nth-child(4) { width: 7%; }
.ps-org-members-users.ps-has-admin-email th:nth-child(5) { width: 20%; }
.ps-org-members-users.ps-has-admin-email th:nth-child(6) { width: 15%; }
/* Fixed layout means long values must wrap inside their cell (emails especially). */
.ps-org-members-users td { overflow-wrap: anywhere; }
.ps-org-members-empty { margin: .25rem 0; }
/* CR-0134: one role tick-box per line so each tick clearly pairs with its label (the editor was cramped when several
   roles wrapped); and give the Role column more width by narrowing the Other memberships column. */
.ps-roles-editor .ps-role-option { display: block; margin: 1px 0; }
/* CR-0395: a floor-locked role in the multi-role editor — can't be unticked (the last holder), dimmed with a padlock;
   the "Hand roles to…" swap beside the badges is the way to move it. */
.ps-roles-editor .ps-role-option--locked { opacity: .7; cursor: not-allowed; }
/* CR-0137: the role column is consistently aligned — the role-less "—" (`.ps-roles-none`) and the role badges share the
   same alignment so a member with no role doesn't sit off to one side (was right-aligned while roled cells centred).
   CR-0200: LEFT-aligned to sit under its left-aligned header, and sized to its content (the old 10rem min-width +
   centring left a huge airy column the eye couldn't tie to the heading). */
.ps-org-members-users .ps-roles-cell { width: 12%; min-width: 6rem; text-align: left; }
.ps-org-members-users .ps-roles-badges { display: inline-block; text-align: left; }
.ps-org-members-users .ps-other-memberships { width: 9rem; }
/* CR-0200: the Parked heading is one description-sized line with a bold lead. */
.ps-parked-note { margin: .75rem 0 .25rem; }
.ps-parked-note strong { color: #1d2327; }
/* CR-0204: the admin "Invitations" section — collapsed by default, header styled like the section headers. */
.ps-admin-invitations { margin: 1rem 0; }
.ps-admin-invitations > summary { cursor: pointer; background: #ecfdf5; border: 1px solid #a7f3d0; color: #065f46; font-weight: 600; padding: 8px 12px; border-radius: 4px; }
.ps-admin-invitations[open] > summary { border-radius: 4px 4px 0 0; }
/* CR-0225 Inc 3b: the full-manager "New invitation" form on [ps_membership_manage] (both org contexts). */
.ps-admin-invite { margin: .6rem 0; }
.ps-admin-invite > summary { cursor: pointer; font-weight: 600; color: #1d4ed8; padding: .3rem 0; }
.ps-admin-invite__form { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; padding: .6rem; border: 1px solid #d5dbe0; border-radius: 6px; background: #f8fafc; }
.ps-admin-invite__field { display: flex; flex-direction: column; font-size: .9em; gap: .2rem; }
.ps-admin-invite__field input, .ps-admin-invite__field select { min-width: 12rem; }
.ps-admin-invite__actions { display: flex; align-items: center; gap: .6rem; }
.ps-admin-invite__status { color: #b91c1c; font-size: .9em; }
/* CR-0225 Inc 3b-2: the admin-invite compose/preview modal (reuses the .ps-forward-overlay/.ps-forward-modal base). */
.ps-admin-invite-preview { display: block; width: 100%; height: 320px; border: 1px solid #d5dbe0; border-radius: 4px; background: #fff; }
.ps-admin-invite-counter { display: block; margin-top: .2em; color: #6b7680; font-size: .85em; }
.ps-admin-invite-insert, .ps-admin-invite-body { width: 100%; font: inherit; }
.ps-admin-invite-body { min-height: 10em; }
/* CR-0203: the org rows table — the Organisation column narrowed so the longer "Max member slots" heading
   costs nothing; the heading itself may wrap to two lines within its column. */
.ps-org-table th:nth-child(1) { width: 13%; }
.ps-org-table .ps-org-maxslots { white-space: nowrap; }
/* CR-0124: the "Approving…" / error status held in the modal while the approval runs. */
.ps-approve-status { margin-left: .5rem; color: #475569; font-size: .92em; }
.ps-approve-status--error { color: #b91c1c; }
/* CR-0124: "Applicant entered/requested …" hint above the org + tier pickers. */
.ps-approve-info { margin: .1rem 0 .4rem; color: #475569; font-size: .92em; }
.ps-approve-info strong { color: #1e293b; }
.ps-approve-tier-label { display: block; font-weight: 600; color: #1e293b; margin: .5rem 0; }
.ps-approve-tier { display: block; width: 100%; margin-top: .35rem; }
/* CR-0124 Inc 1b: the multi-org mapping step (map to existing / create new). */
.ps-approve-org-section { margin: .5rem 0 .75rem; }
.ps-approve-org-label { font-weight: 600; color: #1e293b; margin: .5rem 0 .25rem; }
.ps-approve-org-mode { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: .5rem; }
.ps-approve-org-search, .ps-approve-org-new-name { display: block; width: 100%; margin-bottom: .35rem; }
.ps-approve-org-results { list-style: none; margin: 0; padding: 0; max-height: 160px; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 6px; }
.ps-approve-org-results:empty { display: none; }
.ps-approve-org-opt { padding: .35rem .5rem; cursor: pointer; }
.ps-approve-org-opt:hover { background: #f1f5f9; }
.ps-approve-org-opt.is-selected { background: #dbeafe; }

/* CR-0162: the Reinstate modal — offer the org's previous members back (tick to restore, role changeable).
   Reuses the shared .ps-migrate-overlay/.ps-migrate-dialog chrome (like the Summary/Approve modals). */
.ps-reinstate-dialog { width: 560px; max-height: 80vh; overflow-y: auto; }
.ps-reinstate-explainer { margin: .25rem 0 .75rem; color: #475569; }
.ps-reinstate-members { list-style: none; margin: .5rem 0 0; padding: 0; max-height: 45vh; overflow-y: auto; border: 1px solid #e2e8f0; border-radius: 6px; }
.ps-reinstate-member { display: flex; align-items: center; gap: .5rem; padding: .45rem .6rem; border-bottom: 1px solid #f1f5f9; }
.ps-reinstate-member:last-child { border-bottom: 0; }
.ps-reinstate-pick { flex: 1 1 auto; display: inline-flex; align-items: center; gap: .4rem; min-width: 0; }
.ps-reinstate-email { color: #64748b; font-size: .9em; overflow-wrap: anywhere; }
.ps-reinstate-role { flex: 0 0 auto; max-width: 12rem; }
/* An excluded member (deleted / reused-relinked WP user) — greyed out, no controls; the reason sits on a
   title hover. cursor:help hints there is an explanation. */
.ps-reinstate-member--excluded { color: #94a3b8; cursor: help; }
.ps-reinstate-member--excluded .ps-reinstate-name,
.ps-reinstate-member--excluded .ps-reinstate-email { color: #94a3b8; }
.ps-reinstate-prev-role { flex: 0 0 auto; color: #94a3b8; font-size: .9em; font-style: italic; }
.ps-reinstate-empty { margin: .5rem 0 0; color: #64748b; }
.ps-reinstate-status { margin-left: .5rem; color: #475569; font-size: .92em; }
.ps-reinstate-status--error { color: #b91c1c; }

/* CR-0089 Inc 3b: the Forward pick + compose modals (front-end manage view). */
.ps-forward-overlay {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	padding: 5vh 1rem;
	background: rgba( 15, 23, 42, .55 );
	overflow: auto;
}
.ps-forward-modal {
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 10px 40px rgba( 0, 0, 0, .25 );
	width: 560px;
	max-width: 100%;
	padding: 1.25rem 1.5rem;
}
.ps-forward-title { margin: 0 0 .75rem; }
.ps-forward-to { margin: 0 0 1rem; color: #374151; }
.ps-forward-field { display: block; margin: 0 0 .85rem; }
.ps-forward-field > span { display: block; font-size: 12px; font-weight: 600; color: #374151; margin-bottom: .25rem; }
.ps-forward-subject { width: 100%; box-sizing: border-box; }
.ps-forward-body { width: 100%; box-sizing: border-box; font-family: monospace; font-size: 13px; }
/* CR-0101: side-by-side "text | visual" for the Message HTML — raw source on the left, a live rendered preview
   iframe on the right. The compose modal widens to fit both panes; they stack on narrow screens. */
.ps-forward-compose { width: 900px; }
.ps-forward-body-split { display: flex; gap: 1rem; align-items: stretch; margin-bottom: .85rem; }
.ps-forward-body-source { flex: 1 1 50%; margin-bottom: 0; display: flex; flex-direction: column; }
.ps-forward-body-source .ps-forward-body { flex: 1 1 auto; min-height: 260px; resize: vertical; }
.ps-forward-body-preview-wrap { flex: 1 1 50%; display: flex; flex-direction: column; }
.ps-forward-preview-label { display: block; font-size: 12px; font-weight: 600; color: #374151; margin-bottom: .25rem; }
.ps-forward-body-preview { flex: 1 1 auto; width: 100%; min-height: 260px; box-sizing: border-box; border: 1px solid #d1d5db; border-radius: 6px; background: #fff; }
@media ( max-width: 700px ) {
	.ps-forward-compose { width: 560px; }
	.ps-forward-body-split { flex-direction: column; }
	.ps-forward-body-preview { min-height: 180px; }
}
.ps-forward-test {
	display: flex;
	gap: .5rem;
	align-items: flex-end;
	flex-wrap: wrap;
	margin: .5rem 0 1rem;
	padding: .75rem;
	background: #f9fafb;
	border: 1px solid #f1f5f9;
	border-radius: 6px;
}
.ps-forward-test .ps-forward-field { margin: 0; flex: 1 1 220px; }
.ps-forward-test-to { width: 100%; box-sizing: border-box; }
.ps-forward-status { font-size: 12px; color: #6b7280; }
.ps-forward-actions { margin-top: 1rem; display: flex; gap: .5rem; justify-content: flex-end; }
.ps-forward-pick-list { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 1rem; }
.ps-forward-pick-item { text-align: left; padding: .6rem .8rem; }
.ps-forward-pick-name { display: block; font-weight: 600; }
.ps-forward-pick-desc { display: block; font-size: 12px; color: #6b7280; margin-top: .15rem; }

/* ─── US0131: combined manage view (legacy parity + responsive) ─────────── */
.ps-membership-manage-table { width: 100%; border-collapse: collapse; background: #fff; }
.ps-membership-manage-table th,
.ps-membership-manage-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
.ps-membership-manage-table thead th { background: #f9fafb; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }
.ps-membership-manage-table tr.ps-row-busy { opacity: .5; }
/* CR-0477 Inc 3: the manager's agreements table. */
.ps-membership-agreements .ps-membership-agreement { border: 1px solid #e5e7eb; border-radius: 6px; margin: 0 0 .75rem; background: #fff; }
.ps-membership-agreements .ps-membership-agreement > summary { cursor: pointer; padding: .6rem .9rem; display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center; }
.ps-membership-agreements .ps-membership-agreement__body { padding: 0 .9rem .9rem; }
.ps-membership-agreements .ps-membership-agreement__actions { margin: .5rem 0 .75rem; }
.ps-membership-agreements .ps-inline-form { display: inline; }
.ps-membership-agreements .ps-log-missing { color: #6b7280; }
.ps-membership-agreements .ps-notice--info { background: #eff6ff; border-left: 4px solid #3b82f6; padding: .5rem .9rem; margin: 0 0 .75rem; }
.ps-membership-actions { white-space: nowrap; }
.ps-membership-actions .ps-action { margin-right: 4px; }

/*
 * The "Receive admin emails" header, stacked ONE WORD PER LINE so its column can shrink to little more than the
 * checkbox it contains — the width it releases goes to Role (which must fit the longest role label plus the
 * floor-lock padlock on one line) and to Actions (Edit roles + Remove side by side).
 *
 * `word-spacing: 100vw` forces the break instead of hard-coding <br>s, so the stacking survives translation into a
 * language with a different word count. `padding-right: 0` reclaims the gutter, and the cells centre under it.
 */
.ps-membership-manage-table th.ps-col-admin-email {
	word-spacing: 100vw;
	overflow-wrap: break-word;
	line-height: 1.2;
	/* BG0167: the stacked header is now the column's only floor, so trim what sets it — a smaller size and no
	   letter-spacing take several pixels off the longest word ("RECEIVE"), which is what the column ends up being. */
	font-size: 10px;
	letter-spacing: 0;
	padding-left: 4px;
	padding-right: 4px;
	text-align: center;
}
.ps-membership-manage-table td.ps-admin-email { text-align: center; padding-left: 4px; padding-right: 4px; }

/*
 * BG0167: SHRINK-TO-FIT for the two content-sized columns. `width: 1%` + nowrap is the standard auto-table-layout
 * idiom — already used here by `.ps-dir-alias-guide-col` and the mapping-table remove columns — and it is what
 * percentages could not achieve: under `table-layout: auto` a percentage is only a HINT, so an 8% column still
 * rendered far wider than the checkbox inside it. These two shrink to their content and the slack goes to
 * Name / Email / Other memberships / Actions, which is where it is wanted.
 */
.ps-membership-manage-table th.ps-col-admin-email,
.ps-membership-manage-table td.ps-admin-email { width: 1%; }
/* BG0171: the CELL keeps nowrap (one line for the checkbox); the HEADER must NOT have it. `word-spacing: 100vw`
   above stacks the header only because the words WRAP — with `nowrap` they cannot, so the header became one line of
   "RECEIVE" + 100vw + "ADMIN" + 100vw + "EMAILS", whose min-content width crushed every other column. */
.ps-membership-manage-table td.ps-admin-email { white-space: nowrap; }
/* Role: shrink-to-fit WITHOUT cell-level nowrap — the badges already refuse to wrap (their own rule), while the
   hidden inline role editor in the same cell must still be free to wrap when it is opened. */
.ps-membership-manage-table th.ps-col-role,
.ps-membership-manage-table td.ps-roles-cell { width: 1%; }
.ps-membership-manage-table th.ps-col-role { white-space: nowrap; }

/*
 * Role badges must not wrap mid-label — the padlock rides alongside the label. Scoped to the BADGES, not the cell:
 * the same cell also holds the (hidden) inline role editor, and nowrap there would force its controls onto one line.
 */
.ps-membership-manage-table td.ps-roles-cell .ps-roles-badges { white-space: nowrap; }

.ps-btn {
	display: inline-block;
	border: 1px solid #d1d5db;
	background: #f9fafb;
	color: #1f2937;
	padding: 4px 10px;
	border-radius: 4px;
	font-size: 12px;
	cursor: pointer;
	line-height: 1.4;
}
.ps-btn:hover { background: #f3f4f6; }
/* CR-0214: the lone "New invitation" button on a NON-org [ps_owner_management] surface is the whole call-to-action,
   so it is doubled in size (font + padding, vs the base .ps-btn) with a fully rounded 25px radius. Scoped to the
   invite-only panel so the org-panel invite buttons keep their compact table-row size. */
.ps-owner--invite-only .ps-owner__invite-open { font-size: 24px; padding: 8px 20px; border-radius: 25px; }
/* CR-0215: the admin org-context picker sits above the console for a full-membership admin. */
.ps-owner__admin-picker { margin: 0 0 14px; }
.ps-owner__admin-picker-label { font-weight: 600; }
.ps-owner__admin-picker .ps-admin-org-picker { margin-left: 6px; min-width: 16rem; }
.ps-owner__admin-hint { color: #6b7280; font-style: italic; }
/* CR-0217: [ps_membership_manage_multi] pill tabs. */
.ps-manage-multi-tabs { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 16px; border-bottom: 1px solid #e5e7eb; padding-bottom: 8px; }
.ps-manage-multi-tab { background: none; border: 0; padding: 4px 2px; cursor: pointer; opacity: .55; border-bottom: 2px solid transparent; margin-bottom: -9px; }
.ps-manage-multi-tab:hover { opacity: .8; }
.ps-manage-multi-tab.is-active { opacity: 1; border-bottom-color: #2563eb; }
.ps-manage-multi-panel[hidden] { display: none; }
.ps-manage-multi-log { margin-top: 18px; }
/* CR-0103: in-progress state — a spinning ring before the label while an action (e.g. preparing the Forward popup)
   is running. Works on light and coloured buttons: the ring's track is faint black, its head follows the text colour. */
.ps-btn-busy { pointer-events: none; opacity: .85; }
.ps-btn-busy::before {
	content: "";
	display: inline-block;
	width: 11px;
	height: 11px;
	margin-right: 6px;
	vertical-align: -1px;
	border: 2px solid rgba( 0, 0, 0, .25 );
	border-top-color: currentColor;
	border-radius: 50%;
	animation: ps-btn-spin .6s linear infinite;
}
@keyframes ps-btn-spin { to { transform: rotate( 360deg ); } }
@media ( prefers-reduced-motion: reduce ) { .ps-btn-busy::before { animation: none; } }
.ps-btn-primary { background: #2563eb; color: #fff; border-color: #1d4ed8; }
.ps-btn-primary:hover { background: #1d4ed8; }
.ps-btn-warn { background: #f59e0b; color: #fff; border-color: #d97706; }
.ps-btn-warn:hover { background: #d97706; }

/* CR-0287: the [ps_add_tags]/[ps_remove_tags] button-mode wrapper + its confirmation line. */
.ps-tag-mutate-wrap { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ps-tag-mutate__msg { font-size: 13px; color: #16794c; }
.ps-btn-danger { background: #dc2626; color: #fff; border-color: #b91c1c; }
.ps-btn-danger:hover { background: #b91c1c; }
/* BG0061: the inline role-editor Save/Cancel match the action-button size, in light green / light red. */
.ps-btn-save { background: #dcfce7; color: #166534; border-color: #86efac; }
.ps-btn-save:hover { background: #bbf7d0; }
.ps-btn-cancel { background: #fee2e2; color: #991b1b; border-color: #fca5a5; }
.ps-btn-cancel:hover { background: #fecaca; }
/* CR-0190: a disabled button is BLOCKED, not busy — `wait` read as a spinner. The busy state is `.ps-btn-busy`. */
.ps-btn[disabled] { opacity: .55; cursor: not-allowed; }
/* CR-0192: parked over-limit ex-members in the Invitations list. */
.ps-owner__invite-kind { color: #92400e; font-size: 12px; font-style: italic; }
.ps-owner__invite-row--parked td { background: #fffbeb; }
/* BG0061: a member with no roles shows a centred muted dash instead of "No roles". */
.ps-roles-none { display: block; text-align: center; color: #9ca3af; }

/* ─── BG0062: activity log (legacy parity) ─────────────────────────────── */
.ps-membership-activity-table { width: 100%; border-collapse: collapse; background: #fff; }
.ps-membership-activity-table th,
.ps-membership-activity-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
.ps-membership-activity-table thead th { background: #f9fafb; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }
/* CR-0146: sortable activity-log headers — the whole header is a click target that flips asc/desc. */
.ps-membership-activity-table thead th { padding: 0; }
.ps-activity-sort { display: flex; align-items: center; gap: 4px; width: 100%; padding: 8px 12px; background: none; border: 0; cursor: pointer; font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit; text-align: left; }
.ps-activity-sort:hover { color: #2271b1; }
.ps-activity-sort.is-active { color: #111827; font-weight: 600; }
.ps-activity-sort-arrow { font-size: 10px; }
.ps-activity-pagination { margin-top: 10px; }
.ps-event-when { color: #6b7280; }
.ps-stage-badge { display: inline-block; padding: 2px 10px; border-radius: 10px; font-size: 12px; font-weight: 500; }
/* BG0063: scope the stage colours to the BADGE — the members table also carries .ps-stage--members and must NOT be tinted. */
.ps-stage-badge.ps-stage--applicants { background: #fef3c7; color: #92400e; }
.ps-stage-badge.ps-stage--more_info { background: #e0e7ff; color: #3730a3; }
.ps-stage-badge.ps-stage--members { background: #d1fae5; color: #065f46; }
.ps-stage-badge.ps-stage--rejected { background: #fee2e2; color: #991b1b; }
.ps-stage-badge.ps-stage--left,
.ps-stage-badge.ps-stage--deleted,
.ps-stage-badge.ps-stage--detached { background: #f3f4f6; color: #6b7280; }
.ps-event-arrow { color: #9ca3af; margin: 0 6px; }
/* CR-0028 inc6: "other memberships" column pills (optional column, behaviour show_other_memberships_column). */
.ps-other-membership-pill { display: inline-block; padding: 2px 8px; margin: 0 2px 2px 0; border-radius: 10px; font-size: 12px; background: #eef2ff; color: #3730a3; }
/* CR-0091: each other membership shown as a phase pill + name; name muted unless the person is a Member. */
.ps-other-membership { display: inline-flex; align-items: center; gap: 4px; margin: 0 8px 3px 0; white-space: nowrap; }
.ps-other-membership-name { font-size: 13px; color: #1f2937; }
.ps-other-membership-name--muted { color: #9ca3af; }
/* CR-0196: the membership now renders as its configured pill; a non-member phase dims the whole entry. */
.ps-other-membership--dim { opacity: .55; }
.ps-mstage-pill { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 600; line-height: 1.6; }
.ps-mstage-pill--mem { background: #dcfce7; color: #166534; }   /* member — green */
.ps-mstage-pill--app { background: #fef9c3; color: #854d0e; }   /* applicant / more-info — amber */
.ps-mstage-pill--rej { background: #fee2e2; color: #991b1b; }   /* rejected — red */
/* CR-0026: role-change pill in the activity log's Change column. */
.ps-role-event { display: inline-block; padding: 2px 10px; border-radius: 10px; font-size: 12px; font-weight: 500; }
.ps-role-event--added { background: #dcfce7; color: #166534; }
.ps-role-event--removed { background: #fee2e2; color: #991b1b; }
.ps-source-badge { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 11px; font-weight: 500; background: #e5e7eb; color: #374151; }
.ps-source--engine { background: #dbeafe; color: #1e3a8a; }
.ps-source--fcrm_observed { background: #f3e8ff; color: #6b21a8; }
.ps-source--implied { background: #ecfccb; color: #3f6212; }
.ps-mute { color: #9ca3af; }
@media (max-width: 640px) {
	.ps-membership-activity-table,
	.ps-membership-activity-table tbody,
	.ps-membership-activity-table tr,
	.ps-membership-activity-table td { display: block; width: 100%; }
	.ps-membership-activity-table thead { display: none; }
	.ps-membership-activity-table tr { background: #fff; border: 1px solid #e5e7eb; border-radius: 6px; margin-bottom: 10px; padding: 12px 14px; }
	.ps-membership-activity-table td { border: none; padding: 6px 0; }
	.ps-membership-activity-table td::before { content: attr(data-label); display: block; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; margin-bottom: 2px; }
}

/* Coloured section dividers — yellow applicants, indigo more-info, red rejected. */
.ps-membership-manage-table .ps-section-header th {
	background: #f3f4f6;
	color: #1f2937;
	text-transform: none;
	letter-spacing: 0;
	font-size: 13px;
	font-weight: 600;
	padding: 10px 12px;
	border-top: 2px solid #d1d5db;
	border-bottom: 1px solid #d1d5db;
}
.ps-membership-manage-table .ps-section-header--applicants th { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.ps-membership-manage-table .ps-section-header--more_info th { background: #e0e7ff; color: #3730a3; border-color: #c7d2fe; }
.ps-membership-manage-table .ps-section-header--rejected th { background: #fee2e2; color: #991b1b; border-color: #fecaca; }
.ps-membership-manage-table .ps-section-count { font-weight: normal; opacity: .7; margin-left: 6px; }
.ps-membership-manage-table .ps-section-empty td { color: #6b7280; font-size: 12px; background: #fafbfc; }
.ps-membership-manage-table tbody > tr.ps-section-header:first-child th { border-top: none; }

/* Email mailto links — dotted underline, blue on hover (legacy). */
.ps-mailto-link { color: inherit; text-decoration: none; border-bottom: 1px dotted #9ca3af; }
.ps-mailto-link:hover { color: #2563eb; border-bottom-color: #2563eb; }

/* CR-0027: Existing-members block reads as a continuation of the moderation table — a green (members) section
   header line, flush with the table above, and a consistently-styled table/toolbar/pagination below it. */
.ps-manage-members { margin-top: 14px; border: 1px solid #d1d5db; border-radius: 6px; overflow: hidden; }
.ps-manage-members > summary.ps-members-panel-summary {
	cursor: pointer; padding: 10px 12px; font-size: 13px; font-weight: 600; list-style: none;
	background: #d1fae5; color: #065f46; border-bottom: 1px solid #a7f3d0;
}
.ps-manage-members > summary::-webkit-details-marker { display: none; }
.ps-manage-members .ps-members-panel-count { font-weight: normal; opacity: .7; }
.ps-manage-members .ps-members-panel { padding: 12px 14px; }
/* The members table matches the moderation table's header/cell treatment (it carries .ps-membership-manage-table). */
.ps-members-table { margin: 0; }
/* CR-0174: give the Roles column more room and take it from "Other memberships", which is very wide — the memberships
   pills wrap within a capped column instead of stretching the row. Scoped to the person-centric members table's cells. */
.ps-members-table td.ps-roles-cell,
.ps-members-table th.ps-roles-head { min-width: 9rem; }
.ps-members-table td.ps-other-memberships,
.ps-members-table th.ps-other-head { max-width: 22rem; }
/* CR-0414: each membership on its OWN line. Two side by side made the column claim the width of its widest PAIR
   and ragged everything under it; one per line reads as the list it is, and the column sizes to the longest single
   entry. (Previously inline-block.) */
.ps-members-table td.ps-other-memberships .ps-other-membership { display: block; }

/* CR-0027 item 5/6: search box with a leading "Search" label, spaced from the count line below it. */
.ps-members-toolbar { margin-bottom: 12px; }
.ps-members-search-label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: #374151; }
.ps-members-search { padding: 5px 9px; border: 1px solid #d1d5db; border-radius: 4px; font-size: 13px; min-width: 220px; font-weight: normal; }
.ps-members-count { margin: 0 0 10px; color: #6b7280; font-size: 13px; }

/* CR-0027 item 7: pagination laid out with horizontal spacing; buttons consistent with the table (.ps-btn). */
.ps-members-pagination { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 14px; }
.ps-members-page-indicator { font-size: 13px; color: #6b7280; }
.ps-members-perpage { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #374151; margin-left: auto; }
.ps-members-perpage-select { padding: 3px 6px; border: 1px solid #d1d5db; border-radius: 4px; font-size: 13px; }

/* Touch-friendly tap targets. */
@media (hover: none) and (pointer: coarse) {
	.ps-membership .ps-btn { min-height: 36px; padding: 6px 14px; }
}

/* BG0211: the manage table's wrapper. Two jobs, layered so the fix cannot fail closed:
   1. `container-type: inline-size` makes it a SIZE CONTAINER, so the stacked-card layout below can trigger on the
      COLUMN's width. The card layout was gated on a VIEWPORT media query, so a site with a deliberately narrow
      content column and a wide viewport never got it — the table overflowed and the Actions cell was unreachable.
   2. `overflow-x: auto` guarantees the Actions cell can still be REACHED where container queries are unsupported,
      or when even the stacked layout is wider than the column. A control you cannot reach is a control you do not
      have, so the scroll is the floor beneath the nicer behaviour, never the only answer. */
.ps-members-scroll { container-type: inline-size; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ≤640px: the manage table flips to stacked cards (each cell labelled by data-label). */
@media (max-width: 640px) {
	.ps-membership-manage-table { background: transparent; border: none; }
	.ps-membership-manage-table thead { display: none; }
	.ps-membership-manage-table,
	.ps-membership-manage-table tbody,
	.ps-membership-manage-table tr,
	.ps-membership-manage-table td { display: block; width: 100%; }
	/* BG0218: `tr { display: block }` above OVERRIDES the [hidden] attribute, whose only power is a UA
	   `display: none`. Without this the org member list — a `<tr class="ps-org-members-detail" hidden>` closed by
	   default — is forced OPEN on every narrow viewport, which is why the mobile list was endless. The attribute
	   selector out-specifies the rule above it, so no !important is needed. */
	.ps-membership-manage-table tr[hidden],
	.ps-membership-manage-table td[hidden] { display: none; }
	/* Stacked cards are one column wide, so a sticky Actions cell has nothing to stick to. */
	.ps-membership-manage-table .ps-membership-actions,
	.ps-membership-manage-table th.ps-col-actions { position: static; }
	.ps-membership-manage-table tbody > tr:not(.ps-section-header):not(.ps-section-empty) {
		background: #fff;
		border: 1px solid #e5e7eb;
		border-radius: 6px;
		margin-bottom: 10px;
		padding: 12px 14px;
	}
	.ps-membership-manage-table td { border: none; padding: 6px 0; text-align: left; }
	.ps-membership-manage-table td::before {
		content: attr(data-label);
		display: block;
		font-size: 11px;
		font-weight: 600;
		text-transform: uppercase;
		letter-spacing: .04em;
		color: #6b7280;
		margin-bottom: 2px;
	}
	.ps-membership-manage-table td:not([data-label])::before { content: ''; display: none; }
	.ps-membership-manage-table .ps-membership-actions { margin-top: 8px; padding-top: 8px; border-top: 1px dashed #e5e7eb; white-space: normal; }
	.ps-membership-manage-table .ps-membership-actions::before { display: none; }
	.ps-membership-manage-table .ps-membership-actions .ps-btn { margin: 4px 6px 4px 0; font-size: 13px; padding: 7px 14px; min-height: 36px; }
	.ps-membership-manage-table .ps-section-header { display: block; background: transparent; border: none; padding: 0; margin: 14px 0 6px; }
	.ps-membership-manage-table .ps-section-header th { display: block; width: 100%; text-align: left; padding: 8px 12px; border-radius: 6px; }
	.ps-membership-manage-table tbody > tr.ps-section-header:first-child { margin-top: 0; }
	.ps-membership-manage-table .ps-section-empty td { background: #fafbfc; border: 1px dashed #e5e7eb; border-radius: 6px; padding: 10px 14px; }
	.ps-membership-manage-table .ps-section-empty td::before { display: none; }
}

/* BG0211: the same stacked-card layout, triggered by the CONTAINER's width so a narrow column gets it too. */
@container (max-width: 640px) {
	.ps-membership-manage-table { background: transparent; border: none; }
	.ps-membership-manage-table thead { display: none; }
	.ps-membership-manage-table,
	.ps-membership-manage-table tbody,
	.ps-membership-manage-table tr,
	.ps-membership-manage-table td { display: block; width: 100%; }
	/* BG0218: `tr { display: block }` above OVERRIDES the [hidden] attribute, whose only power is a UA
	   `display: none`. Without this the org member list — a `<tr class="ps-org-members-detail" hidden>` closed by
	   default — is forced OPEN on every narrow viewport, which is why the mobile list was endless. The attribute
	   selector out-specifies the rule above it, so no !important is needed. */
	.ps-membership-manage-table tr[hidden],
	.ps-membership-manage-table td[hidden] { display: none; }
	/* Stacked cards are one column wide, so a sticky Actions cell has nothing to stick to. */
	.ps-membership-manage-table .ps-membership-actions,
	.ps-membership-manage-table th.ps-col-actions { position: static; }
	.ps-membership-manage-table tbody > tr:not(.ps-section-header):not(.ps-section-empty) {
		background: #fff;
		border: 1px solid #e5e7eb;
		border-radius: 6px;
		margin-bottom: 10px;
		padding: 12px 14px;
	}
	.ps-membership-manage-table td { border: none; padding: 6px 0; text-align: left; }
	.ps-membership-manage-table td::before {
		content: attr(data-label);
		display: block;
		font-size: 11px;
		font-weight: 600;
		text-transform: uppercase;
		letter-spacing: .04em;
		color: #6b7280;
		margin-bottom: 2px;
	}
	.ps-membership-manage-table td:not([data-label])::before { content: ''; display: none; }
	.ps-membership-manage-table .ps-membership-actions { margin-top: 8px; padding-top: 8px; border-top: 1px dashed #e5e7eb; white-space: normal; }
	.ps-membership-manage-table .ps-membership-actions::before { display: none; }
	.ps-membership-manage-table .ps-membership-actions .ps-btn { margin: 4px 6px 4px 0; font-size: 13px; padding: 7px 14px; min-height: 36px; }
	.ps-membership-manage-table .ps-section-header { display: block; background: transparent; border: none; padding: 0; margin: 14px 0 6px; }
	.ps-membership-manage-table .ps-section-header th { display: block; width: 100%; text-align: left; padding: 8px 12px; border-radius: 6px; }
	.ps-membership-manage-table tbody > tr.ps-section-header:first-child { margin-top: 0; }
	.ps-membership-manage-table .ps-section-empty td { background: #fafbfc; border: 1px dashed #e5e7eb; border-radius: 6px; padding: 10px 14px; }
	.ps-membership-manage-table .ps-section-empty td::before { display: none; }
}

/* CR-0410: the email column collapses to an icon, and the Actions column stops scrolling out of reach.
   ------------------------------------------------------------------------------------------------------
   These two are one fix. The address was ~28% of the table for a value a manager reads rarely and clicks less,
   and that width is what pushed Actions off the side. Shrinking it buys the room back; sticking Actions to the
   right edge guarantees the buttons are reachable even when the table still overflows. */
.ps-email {
	display: inline-flex;
	align-items: center;
	position: relative;
	color: #4b5563;
	text-decoration: none;
	line-height: 1;
	padding: 2px;
	border-radius: 3px;
}
.ps-email:hover, .ps-email:focus-visible { color: #1d4ed8; }
.ps-email:focus-visible { outline: 2px solid #2563eb; outline-offset: 1px; }
.ps-email__icon { display: block; }

/* The tip appears with NO delay — scanning a column of addresses is the point, and a native `title` waits about a
   second. It opens to the RIGHT, vertically centred inside its own row: `.ps-members-scroll` is an overflow
   container, so anything extending above or below the row would simply be clipped. */
.ps-email__tip {
	position: absolute;
	left: 100%;
	top: 50%;
	transform: translateY(-50%);
	margin-left: 6px;
	display: none;
	white-space: nowrap;
	background: #111827;
	color: #fff;
	font-size: 12px;
	line-height: 1.4;
	padding: 4px 8px;
	border-radius: 4px;
	z-index: 5;
	pointer-events: none;
}
.ps-email:hover .ps-email__tip,
.ps-email:focus-visible .ps-email__tip { display: block; }
.ps-mailto-invalid { color: #b32d2e; }

/* CR-0414: the full address, shown only when the table's CONTAINER is wide enough to afford it. The markup always
   carries both presentations; these rules choose. Default = hidden (the compact icon), so browsers without
   container queries — and every narrow column — keep the CR-0410 behaviour unchanged. */
.ps-email__addr { display: none; }
@container (min-width: 900px) {
	.ps-email__addr { display: inline; margin-left: 6px; font-size: 13px; color: #1f2937; }
	.ps-email:hover .ps-email__addr, .ps-email:focus-visible .ps-email__addr { color: #1d4ed8; }
	/* The address is on screen — a tooltip repeating it would just chase the cursor. */
	.ps-email:hover .ps-email__tip,
	.ps-email:focus-visible .ps-email__tip { display: none; }
	/* The column may now take its content's width; nowrap (from CR-0410) keeps the address on one line. */
}

/* Shrink-to-fit, the idiom BG0167 already uses for content-sized columns in this table. */
.ps-membership-manage-table td.ps-col-email,
.ps-membership-manage-table th.ps-col-email,
.ps-owner__members td.ps-owner__email,
.ps-owner__members th.ps-col-email { width: 1%; white-space: nowrap; }

/* Actions pinned to the right edge so they are reachable without panning. A background is required — the rest of
   the row scrolls UNDER this cell, and a transparent one would let it show through. */
.ps-membership-manage-table th.ps-col-actions,
.ps-membership-manage-table td.ps-membership-actions,
.ps-owner__members th.ps-col-actions,
.ps-owner__members td.ps-owner__actions {
	position: sticky;
	right: 0;
	background: #fff;
	/* Two shadows, both load-bearing. The left one separates the pinned cell from the row scrolling under it.
	   The INSET one redraws the row separator: this table is `border-collapse: collapse`, where a cell's borders
	   are painted by the TABLE rather than the cell, so a sticky cell travels without its own bottom border and
	   the row line breaks exactly where the eye follows it. A shadow is painted by the cell, so it comes along. */
	box-shadow: inset 0 -1px 0 #f1f5f9, -6px 0 6px -6px rgba(0, 0, 0, .18);
}
.ps-membership-manage-table thead th.ps-col-actions,
.ps-owner__members thead th.ps-col-actions { background: #f6f7f7; }

/* ≤380px: full-width action buttons so nothing overflows. */
@media (max-width: 380px) {
	.ps-membership-manage-table .ps-membership-actions .ps-btn { display: block; width: 100%; margin: 4px 0 0; text-align: center; }
}

/* CR-0042: a Delete action locked to WordPress admins (membership deletes the CRM contact on delete). */
.ps-action-locked { opacity: .5; cursor: not-allowed; }

/* CR-0169: front-end tier management — the manager modals reuse the .ps-migrate chrome; add the request meta + the
   member-facing request surface. Pills are self-styled (inline colour) by TierPill. */
/* BG0112: the tier dialog reuses .ps-migrate-dialog, which has no height cap — so a full tier dialog (context rows +
   capacity-impact warning + cost + acknowledgement + status) overflowed its box. Contain + scroll it, matching the
   sibling .ps-summary-dialog / .ps-reinstate-dialog, and widen it a touch to fit the extra content. */
.ps-tier-dialog { width: 560px; max-height: 80vh; overflow-y: auto; }
.ps-tier-dialog .ps-tier-field { display: block; margin: 0 0 8px; }
.ps-tier-dialog .ps-tier-cost { margin: 4px 0; color: #664d03; background: #fff3cd; border: 1px solid #ffe69c; border-radius: 4px; padding: 6px 8px; font-size: 13px; }
.ps-tier-dialog .ps-tier-ack-label { display: block; margin: 0 0 8px; }
.ps-tier-status--error { color: #b32d2e; }
.ps-tier-req-meta { display: grid; grid-template-columns: max-content 1fr; gap: 2px 10px; margin: 0 0 10px; }
.ps-tier-req-meta dt { font-weight: 600; }
.ps-tier-req-meta dd { margin: 0; }
/* CR-0187: red capacity-impact warning shown when the chosen tier cannot seat members + invitations. */
.ps-tier-dialog .ps-tier-impact { color: #b32d2e; font-weight: 600; margin: 4px 0 8px; }
.ps-tier-dialog .ps-tier-impact[hidden] { display: none; }
.ps-tier-cell .ps-tier-pill, .ps-tier-request .ps-tier-pill { vertical-align: middle; }
/* CR-0175: the front-end tier pill (roster, member request, activity log) — the same treatment the admin editor gives
   it, fully rounded (radius 25 is also inlined by TierPill::render). */
.ps-tier-pill {
	display: inline-block;
	border-radius: 25px;
	padding: 1px 10px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.6;
	white-space: nowrap;
}
.ps-tier-pill--muted { background: #f1f5f9; color: #94a3b8; }
.ps-tier-request-block { margin: 0 0 16px; padding: 12px; border: 1px solid #e2e8f0; border-radius: 6px; }
.ps-tier-request-head { margin: 0 0 8px; }
.ps-tier-request-org { font-weight: 600; }
.ps-tier-request-current { margin-left: 8px; }
.ps-tier-request-form .ps-tier-request-label { display: block; margin: 0 0 6px; }
.ps-tier-request-cost { margin: 4px 0; color: #664d03; background: #fff3cd; border: 1px solid #ffe69c; border-radius: 4px; padding: 6px 8px; font-size: 13px; }
.ps-tier-request-ack-label { display: block; margin: 0 0 8px; }
.ps-tier-request-status--error { color: #b32d2e; }
.ps-tier-request-pending { margin: 4px 0; font-style: italic; }

/* CR-0229 Inc 3 · CR-0241 Inc 1: the member-facing programme view ([ps_programme]) — Landing Pad-style element cards. */
.ps-programme { margin: 1.5em 0; }
.ps-programme__title { margin: 0 0 .25em; }
.ps-programme__desc { margin: 0 0 1em; color: #50575e; }
.ps-programme__elements { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

/* The card row + its flex face. */
.ps-programme-el { position: relative; border: 1px solid #e2e4e7; border-radius: 6px; background: #fff; transition: border-color .15s; }
.ps-programme-el:hover { border-color: #b4b9be; }
/* CR-0312 (feedback): let the head wrap so a pill/meta + action stack instead of squeezing side-by-side on narrow
   cards (with align-items:flex-start once wrapped they line up cleanly). */
.ps-programme-el__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 10px 14px; }
.ps-programme-el--child { margin-left: 24px; border-left: 3px solid #e0e0e0; }

/* CR-0310: "Locked by tags" — the whole element is locked for the viewer: a padlock overlays it, and every action
   button/link is inert except the info (i) toggle (also enforced by the programme-view.js click guard). */
.ps-programme-el.is-locked { border-style: dashed; }
.ps-programme-el.is-locked > .ps-programme-el__head .ps-programme-el__name-wrap,
.ps-programme-el.is-locked > .ps-programme-el__head .ps-programme-el__thumb,
/* CR-0311/CR-0312 (feedback): dim the head META too (the org name/count/tier + pill) so a locked card's data reads as
   greyed-out like the rest of the element, not full-strength beside the greyed buttons. */
.ps-programme-el.is-locked > .ps-programme-el__head .ps-space-el__meta,
.ps-programme-el.is-locked > .ps-programme-el__head .ps-tier-el__meta { opacity: .6; }
/* Pill-shaped like the buttons it rides (operator, 2026-08-28) — same silhouette, its own neutral colour. */
.ps-programme-el__lock { position: absolute; top: 8px; right: 10px; z-index: 4; display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 26px; padding: 0 9px; border: 0; border-radius: 999px; background: #f0f0f1; box-shadow: 0 1px 2px rgba(0,0,0,.18); cursor: help; box-sizing: border-box; }
.ps-programme-el__lock-glyph { font-size: 14px; line-height: 1; }
/* CR-0310 (feedback): the lock message popup — revealed by clicking the padlock (programme-view.js toggles [hidden]). */
/* CR-0310 follow-up: the lock message is an INSTANT hover tooltip — the click popup left stuck boxes behind, and a
   native `title` cannot show without the OS delay. Hidden by default; shown the moment the locked card is hovered or
   the padlock focused. `width: max-content` sizes it by its TEXT (an abspos box otherwise shrink-fits to the width of
   the button it hangs off); `pointer-events: none` so it can never trap a click or need clicking away. */
/* CR-0461: a family binding with no resolvable community hides its decision — no required tick for absent terms. */
.ps-agreement--unavailable { display: none; }
.ps-programme-el__lock-msg { display: none; position: absolute; top: 40px; right: 10px; z-index: 5; width: max-content; max-width: 260px; padding: 8px 12px; border-radius: 6px; background: #1d2327; color: #fff; font-size: 13px; line-height: 1.4; box-shadow: 0 2px 8px rgba(0,0,0,.25); pointer-events: none; }
.ps-programme-el.is-locked:hover .ps-programme-el__lock-msg,
.ps-programme-el__lock:focus-visible ~ .ps-programme-el__lock-msg { display: block; }
/* CR-0312 (feedback): the padlock is attached to the action button — the button is wrapped so the badge always sits on
   its top-right corner and travels with it (wraps together, never floats in the card corner). The message popup then
   hangs off the button. Cards with NO action button keep the original corner overlay (.ps-programme-el__lock-corner). */
.ps-programme-el__lockwrap { position: relative; display: inline-flex; }
.ps-programme-el__lockwrap .ps-programme-el__lock { top: -10px; right: -10px; }
.ps-programme-el__lockwrap .ps-programme-el__lock-msg { top: calc(100% + 6px); right: 0; }
/* The wrapped button inherits the right-push the bare button used to carry, so a locked slots card keeps its button right. */
.ps-seats-el .ps-programme-el__lockwrap { margin-left: auto; }
/* CR-0310 (feedback): a locked element's info body stays READABLE but is dimmed + shielded — a semi-transparent overlay
   over the body intercepts pointer events so its links/buttons can't be triggered, and a "no-entry" cursor makes clear
   it's unavailable. The (i) toggle (in the head, not the body) still opens/closes it. */
.ps-programme-el.is-locked .ps-programme-el__body { position: relative; }
.ps-programme-el.is-locked .ps-programme-el__body > * { opacity: .6; }
.ps-programme-el.is-locked .ps-programme-el__body::after { content: ""; position: absolute; inset: 0; z-index: 2; cursor: not-allowed; background: rgba(255, 255, 255, .35); }
/* CR-0310 (feedback): "Promotional text" on a locked element becomes the (i) detail — it replaces the member-text body
   and is revealed by the info (i) toggle (hidden by default like any detail). Because the body now holds the promo (not
   the covered member text), it is NOT shielded — fully readable with clickable links. */
.ps-programme-el.is-locked.has-lock-promo .ps-programme-el__body > * { opacity: 1; }
.ps-programme-el.is-locked.has-lock-promo .ps-programme-el__body::after { content: none; }
.ps-programme-el__promo { font-size: 14px; line-height: 1.5; }
.ps-programme-el__promo :first-child { margin-top: 0; }
.ps-programme-el__promo :last-child { margin-bottom: 0; }
.ps-programme-el.is-locked .ps-programme-el__action,
.ps-programme-el.is-locked .ps-programme-claim,
.ps-programme-el.is-locked .ps-programme-el__join,
.ps-programme-el.is-locked .ps-tier-el__request,
.ps-programme-el.is-locked .ps-tier-el__submit,
.ps-programme-el.is-locked .ps-tier-el__cancel,
.ps-programme-el.is-locked .ps-programme-el__thumb-link { pointer-events: none; opacity: .5; cursor: not-allowed; }
/* CR-0310 (feedback): a LOCKED group's collapse toggle stays clickable (it starts collapsed but can be opened/closed) —
   so it is deliberately NOT in the neutralise list above. It is dimmed with the rest of the head but remains usable. */
.ps-programme-el.is-locked .ps-programme-group-toggle { cursor: pointer; }
/* CR-0310 (feedback): on a locked LINK element the inline hyperlink TEXT + the copy icon are HIDDEN outright — the URL
   is unavailable, so it must not be shown (nor greyed-but-visible). The element's ACTION button (e.g. "Visit") is NOT
   hidden — it stays greyed + inert via the general lock rule above, keeping it consistent with every other locked card.
   The name, pill and shielded info body still read; the thumbnail stays visible but inert (its link is neutralised). */
.ps-programme-el--link_access.is-locked .ps-programme-el__quick a,
.ps-programme-el--link_access.is-locked .ps-programme-el__copy { display: none; }

/* Featured-image thumbnail (16:9; space reserved even when empty so cards align). */
/* CR-0308: no grey box behind the featured image — it sits on the card, centred in its reserved slot. */
.ps-programme-el__thumb { width: 100px; height: 56px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; background: transparent; border: 0; border-radius: 4px; overflow: hidden; }
.ps-programme-el__thumb img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; display: block; }
/* CR-0296 (feedback): centre the image inside a LINKED thumbnail exactly like an unlinked one (flex-centre, not a
   block that pins the image top-left), so every element type's featured image aligns identically. */
.ps-programme-el__thumb-link { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; line-height: 0; transition: opacity .12s; }
.ps-programme-el__thumb-link:hover { opacity: .85; }
.ps-programme-el__thumb--empty { background: transparent; border-color: transparent; }

/* Circular, colour-coded status-icon badge. */
.ps-programme-el__dot { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; background: #eef0f1; color: #6c6f73; }
.ps-programme-el__dot.ps-dot--green { background: #dff5df; color: #1a7a1a; }
.ps-programme-el__dot.ps-dot--amber { background: #fcf0d4; color: #996800; }
.ps-programme-el__dot.ps-dot--grey { background: #eef0f1; color: #6c6f73; }
.ps-programme-el--group > .ps-programme-el__head .ps-programme-el__dot,
.ps-programme-el--programme_integration > .ps-programme-el__head .ps-programme-el__dot { background: #ebe3f1; color: #6c3483; }
.ps-programme-el__icon { display: block; }
/* CR-0256: an ungated link element (tick conditions off) — the status badge itself is a link that opens the target. */
.ps-programme-el__badge-link { display: inline-flex; line-height: 0; text-decoration: none; border-radius: 50%; }
.ps-programme-el__badge-link:hover .ps-programme-el__dot { background: #e4eefb; color: #135e96; }

/* Name + quick-info. CR-0255: stack the name over the link (column, left-aligned) so both get the full card width —
   more room for long names and long links — and nudge the block up to sit tight under the name. */
/* CR-0312 (feedback): a min-width floor + word-breaking so the name/text area never collapses to a single character
   per line on a narrow card — it wraps at a readable width, and the action/pill wrap to the next line instead. */
.ps-programme-el__name-wrap { flex: 1 1 8rem; min-width: 8rem; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px; overflow-wrap: anywhere; }
/* CR-0246: larger + bolder element name, closer to the legacy Landing Pad look. The group-header rule below keeps its
   own smaller uppercase treatment (its font-size is relative, so it scales down from this base). */
.ps-programme-el__name { font-weight: 700; font-size: 1.0625rem; line-height: 1.25; }
/* CR-0255: the link sits under the name; keep it inline with its copy button, let the link (not the button) truncate. */
.ps-programme-el__quick { max-width: 100%; min-width: 0; display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #555; }
.ps-programme-el__quick a { min-width: 0; color: #2271b1; text-decoration: none; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-programme-el__quick a:hover { text-decoration: underline; }
/* CR-0255: copy-link button after a quick-info link. */
.ps-programme-el__copy { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; background: transparent; border: 0; padding: 2px; margin: 0; cursor: pointer; color: #2271b1; line-height: 1; border-radius: 4px; }
.ps-programme-el__copy:hover { color: #135e96; background: #eef4fb; }
.ps-programme-el__copy-icon { display: block; }
.ps-programme-el__copy-done { display: none; font-size: 12px; font-weight: 600; color: #1a7a1a; }
.ps-programme-el__copy.is-copied .ps-programme-el__copy-icon { display: none; }
.ps-programme-el__copy.is-copied .ps-programme-el__copy-done { display: inline; }
/* BG0120: a group's name matches the other element names (CR-0246 enlarged the base but left this override at .9em). */
.ps-programme-el--group > .ps-programme-el__head .ps-programme-el__name { font-size: 1.0625rem; font-weight: 700; text-transform: none; letter-spacing: normal; color: inherit; }

/* Neutral status pill + action. CR-0255: the action button is fully pill-rounded (25px on every corner). */
.ps-programme-el__status { font-size: 12px; color: #555; background: #f0f0f1; padding: 2px 8px; border-radius: 10px; white-space: nowrap; }
/* CR-0303: the optional per-element decorative pill (config pill_text/pill_colour) — sits alongside the status pill; an
   inline background/text colour (when pill_colour is set) overrides the neutral style. */
.ps-programme-el__pill { flex: 0 0 auto; font-size: 12px; font-weight: 600; color: #555; background: #f0f0f1; padding: 3px 10px; border-radius: 12px; white-space: nowrap; }
/* CR-0308: the pill sits right beside the action (both pushed right by the flexible name-wrap); no auto margin. */
.ps-programme-el__action { margin-left: 0; border-radius: 25px !important; }
.ps-programme-el__text { margin: 0; padding: 0 14px 12px; }

/* CR-0241 Inc 2 / CR-0308: the disclosure (i) toggle now sits in the old icon slot — right after the featured image — so
   no auto margin (it must not push to the right). */
.ps-programme-el__toggle { margin-left: 0; display: inline-flex; align-items: center; justify-content: center; background: #f0f6fc; border: 1px solid #c3d9f0; border-radius: 25px; cursor: pointer; color: #2271b1; font-size: 13px; font-weight: 600; padding: 5px 10px; line-height: 1; }
.ps-programme-el__toggle:hover { color: #135e96; background: #dde8f0; border-color: #2271b1; }
/* CR-0255: an info-circle (closed) / ✕-in-circle (open) disclosure glyph, replacing the play-triangle. */
.ps-programme-el__toggle-glyph { display: inline-flex; align-items: center; justify-content: center; line-height: 1; }
.ps-programme-el__toggle-icon { display: block; }
/* CR-0253: a group's collapse toggle — show/hide its child rows. */
/* CR-0315: the group open/close toggle is a labelled button (glyph + text), not a bare arrow. */
/* Pill-shaped like the sibling action buttons (operator, 2026-08-28), keeping its own light palette. Focus and
   active are pinned to the SAME palette: the theme's `button:focus`/`:active` otherwise painted it purple after a
   click (the button keeps focus once clicked), a state that signified nothing. */
.ps-programme-group-toggle { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; background: #f0f3f7; border: 1px solid #c7d0da; border-radius: 999px; cursor: pointer; color: #1d4b8f; padding: 6px 16px; line-height: 1; font-size: 13px; font-weight: 600; white-space: nowrap; }
.ps-programme-group-toggle:hover,
.ps-programme-group-toggle:focus,
.ps-programme-group-toggle:active { background: #e2e9f2; border-color: #98accb; color: #103a70; }
.ps-programme-group-toggle-glyph { display: inline-block; font-size: 14px; line-height: 1; }
.ps-programme-group-toggle-label { display: inline-block; }
/* The padlock rides the toggle button (they wrap together) but the button stays fully usable. */
.ps-programme-el__lockwrap--group { margin-left: auto; }
.ps-programme-el__lockwrap--group .ps-programme-group-toggle { margin-left: 0; }
.ps-programme-el__body { padding: 8px 14px 14px; border-top: 1px dashed #e2e4e7; color: #1d2327; font-size: 14px; }
.ps-programme-el__member { background: #f8f9fa; padding: 10px 14px; border-radius: 4px; }
.ps-programme-el__detail { margin: 8px 0 0; }
.ps-programme-el__notes { background: #f0f6fc; border-left: 3px solid #2271b1; padding: 10px 14px; margin-top: 10px; border-radius: 0 4px 4px 0; }
.ps-programme-el__notes strong { display: block; margin-bottom: 4px; color: #135e96; font-size: 13px; }
.ps-programme-el__join { display: inline-block; margin-top: 8px; padding: 8px 20px; border-radius: 25px; background: #1a7a1a; color: #fff; font-weight: 600; text-decoration: none; border: 1px solid #1a7a1a; }
.ps-programme-el__join:hover { background: #155f15; border-color: #155f15; }

.ps-programme--signin { color: #50575e; font-style: italic; }

/* CR-0241 Inc 3: the admin editor's live preview — neutralise the action/claim controls so nothing is claimed from the
   editor, but keep the accordion toggle interactive so the operator can still inspect element detail. */
.ps-programme-editor-preview { margin: 1.5em 0; }
.ps-programme-preview { border: 1px solid #e2e4e7; border-radius: 6px; padding: 8px 14px; background: #fdfdfd; }
/* CR-0246: `cursor: not-allowed` so the greying reads as an intentional preview-disabled state, not a broken button. */
.ps-programme-preview .ps-programme-el__action,
.ps-programme-preview .ps-programme-claim,
.ps-programme-preview .ps-programme-el__join { pointer-events: none; opacity: .55; cursor: not-allowed; }

/* CR-0229 Inc 4: the manager programme view ([ps_programme_manage]). */
.ps-programme-manage { margin: 1.5em 0; }
.ps-programme-manage__title { margin: 0 0 .5em; }
.ps-programme-manage__search { margin: 0 0 .75em; display: flex; gap: .5em; flex-wrap: wrap; }
.ps-programme-manage__results { list-style: none; margin: 0 0 1em; padding: 0; }
.ps-programme-manage__result { padding: .3em 0; }
.ps-programme-manage__result.is-selected { font-weight: 600; }
.ps-programme-manage__who { margin: .5em 0 1em; }
.ps-programme-manage__hint, .ps-programme-manage__none { color: #50575e; font-style: italic; }
.ps-pm-elements { list-style: none; margin: 0; padding: 0; }
.ps-pm-el { padding: .75em 0; border-top: 1px solid #e2e4e7; }
.ps-pm-el:first-child { border-top: 0; }
.ps-pm-el--child { padding-left: 1.75em; }
.ps-pm-el__head { display: flex; align-items: center; gap: .5em; flex-wrap: wrap; }
.ps-pm-el__controls { display: flex; align-items: center; gap: .5em; margin-top: .4em; flex-wrap: wrap; }
.ps-pm-el--group > .ps-pm-el__head .ps-programme-el__name { text-transform: uppercase; letter-spacing: .02em; font-size: .9em; color: #50575e; }
.ps-pm-status-label { font-size: .85em; color: #50575e; }
.ps-pm-feedback { font-size: .85em; color: #50575e; }

/* CR-0231 Inc 2b: member "authorised applications" ([ps_oauth_authorised_apps]). */
.ps-oauth-apps__list { list-style: none; margin: 0; padding: 0; }
.ps-oauth-app { display: flex; align-items: center; justify-content: space-between; gap: 1em; padding: .8em 0; border-bottom: 1px solid #e2e4e7; flex-wrap: wrap; }
.ps-oauth-app__main { display: flex; flex-direction: column; gap: .15em; }
.ps-oauth-app__name { font-weight: 600; }
.ps-oauth-app__scopes { font-size: .85em; color: #50575e; }
.ps-oauth-app__since { font-size: .8em; }
.ps-oauth-app__actions { display: flex; align-items: center; gap: .5em; }
.ps-oauth-app__feedback { font-size: .85em; color: #50575e; }
.ps-oauth-apps__empty { color: #50575e; }

/* CR-0239 Inc 2b: the invitation "Progress" column — account/crown icons + a click-to-expand membership-change list. */
/* CR-0243: the cell anchors the crown's floating detail pop-up. */
.ps-progress-cell { white-space: nowrap; position: relative; }
.ps-progress-icon { line-height: 1; margin-right: .3rem; vertical-align: middle; color: #50575e; }
.ps-progress-crown { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; color: #50575e; }
/* CR-0242: mono, outline Progress glyphs (account + crown share one style). CR-0243: doubled in size (~16 → 30px). */
.ps-progress-svg { display: inline-block; vertical-align: middle; width: 30px; height: 30px; }
/* CR-0243: hover tints the crown's OUTLINE in the link blue — no obscuring background highlight, in any state. */
.ps-progress-crown:hover,
.ps-progress-crown:focus { background: none; color: #2271b1; outline: none; }
/* CR-0242: the Invitations + Forwarded-users tracking tables share a fixed layout + column widths so they align. */
.ps-tracking-table { table-layout: fixed; width: 100%; }
.ps-tracking-table th, .ps-tracking-table td { overflow-wrap: anywhere; }
/* CR-0243: the membership-change detail is a floating pop-up (wider than the column, so its text isn't clipped). */
.ps-progress-details { position: absolute; top: 100%; right: 0; z-index: 30; margin-top: .3rem; padding: .6rem .8rem; min-width: 240px; max-width: 340px; background: #fff; border: 1px solid #c3c4c7; border-radius: .3rem; box-shadow: 0 2px 8px rgba( 0, 0, 0, .18 ); font-size: .85rem; white-space: normal; text-align: left; }
.ps-progress-details ul { margin: .2rem 0 0; padding-left: 1.1rem; }

/* CR-0273: Membership tier-request element — crown badge, org name centred above a large current-tier pill, a
   "Membership" type pill, the in-progress state line, and the tier-picker popover. */
.ps-tier-el { position: relative; }
.ps-programme-el__dot.ps-dot--blue { background: #e5eefc; color: #2158b0; }
.ps-tier-el__meta { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.ps-tier-el__orgpill { display: flex; flex-direction: column; align-items: center; gap: 3px; text-align: center; }
.ps-tier-el__org { font-size: 12px; color: #556; font-weight: 700; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* CR-0297: org name bold */
.ps-tier-el__tier { display: inline-block; padding: 6px 16px; border-radius: 20px; background: #2158b0; color: #fff; font-size: 15px; font-weight: 700; line-height: 1.2; border: 1px solid transparent; }
/* CR-0312 (feedback): the current-tier pill is highlighted exactly like the slots card's held-tier pill — a dark ring
   over any tier colour (falls back to the blue box when uncoloured), so the highlight consistently reads as "you own this". */
.ps-tier-el__tier.is-current { box-shadow: 0 0 0 2px #1d2327; }
.ps-tier-el__tier.is-current:not(.has-colour) { background: #e5eefc; border-color: #2158b0; color: #1d2327; box-shadow: none; }
.ps-tier-el__type { font-size: 12px; color: #555; background: #f0f0f1; padding: 3px 10px; border-radius: 12px; white-space: nowrap; }
.ps-tier-el .ps-tier-el__request { margin-left: 12px !important; border-radius: 25px !important; }
/* CR-0273 (feedback): a tier-request button the viewer isn't authorised to use is greyed + shows the no-entry cursor
   (the disabled attribute carries the permission tooltip). */
.ps-tier-el__request:disabled,
.ps-tier-el__request[disabled] { opacity: .5 !important; cursor: not-allowed !important; box-shadow: none !important; }
.ps-tier-el__state { padding: 8px 14px 12px; font-size: 13px; color: #556; }
.ps-tier-el--pending .ps-tier-el__state { color: #7a5b00; }
/* CR-0273 (feedback): a richer owner-console-style dialog (tier picker + cost note + confirmation tick + actions) —
   lay it out as a column so the stacked rows read top-to-bottom. */
.ps-tier-el__pop { position: absolute; right: 14px; top: calc(100% - 6px); z-index: 20; box-sizing: border-box; display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: 320px; max-width: calc(100vw - 32px); padding: 12px 14px; background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,.16); }
.ps-tier-el__pop *, .ps-tier-el__pop *::before, .ps-tier-el__pop *::after { box-sizing: border-box; }
.ps-tier-el__pop[hidden] { display: none; }
/* CR-0273 (feedback fix): the label STACKS (text above the full-width select) — a row layout squeezed the caption to
   one character per line on narrow cards, and the select overflowed. Keep the select inside the box on phones. */
.ps-tier-el__pop-label { display: flex; flex-direction: column; align-items: stretch; gap: 4px; font-size: 13px; }
.ps-tier-el__pop-label select { display: block; width: 100%; max-width: 100%; }
/* CR-0273 (feedback): the cost advisory + confirmation checkbox, mirroring the owner console. */
.ps-tier-el__cost { margin: 0; font-size: 12px; line-height: 1.4; color: #556; }
.ps-tier-el__ack-label { display: flex; align-items: flex-start; gap: 6px; font-size: 12px; color: #1d2327; }
.ps-tier-el__ack-label input { margin-top: 2px; }
.ps-tier-el__actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
/* CR-0293: pill-shaped Submit/Cancel to match the platform's rounded button style. */
.ps-tier-el__submit, .ps-tier-el__cancel { border-radius: 25px; }
.ps-tier-el__submit:disabled { cursor: not-allowed; opacity: .6; }
.ps-tier-el__msg { font-size: 12px; color: #556; min-width: 60px; }
/* CR-0311 Inc 3: the Space Posts card — org name above the post count, the count red when over the limit, and a Post
   button (a chooser popover when several spaces are set). Mirrors the tier card's meta/pop treatment. */
.ps-space-el__meta { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; margin-left: auto; text-align: center; }
.ps-space-el__org { font-weight: 600; }
.ps-space-el__count { font-size: 13px; color: #556; }
.ps-space-el__num { font-weight: 700; color: #1d2327; }
.ps-space-el__num--over { color: #d63638; }
.ps-space-el__post:disabled { cursor: not-allowed; opacity: .6; }
.ps-space-el__pop { position: absolute; right: 14px; top: calc(100% - 6px); z-index: 20; box-sizing: border-box; display: flex; flex-direction: column; gap: 4px; min-width: 200px; max-width: calc(100vw - 32px); padding: 10px 12px; background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,.16); }
.ps-space-el__pop[hidden] { display: none; }
.ps-space-el__pop-label { margin: 0 0 2px; font-size: 12px; color: #556; }
.ps-space-el__choice { display: block; padding: 4px 2px; font-size: 13px; }
@media (max-width: 640px) {
	.ps-space-el__pop { left: 8px; right: 8px; min-width: 0; max-width: none; }
}
/* CR-0312: the Membership slots card — a pane below the head with the organisation's name centred above a row of tier
   pills (each coloured by its tier, showing its base slot count, lowest-left, the current tier boxed), the headline
   total, and an "Add More Slots" popover (a number field + cost note + confirmation tick). CR-0312 (feedback): the
   tier-change-style meta pill was removed, so the "Add More Slots" button right-aligns in the head on its own. */
.ps-seats-el { position: relative; }
/* CR-0312 (feedback): the name yields room so the pill box (org name centred over the tier pills) fits on the head row;
   the "Add More Slots" button keeps its place and only drops to the next line when there isn't room. */
.ps-seats-el__name-wrap { flex: 0 1 auto; min-width: 8rem; }
.ps-seats-el__pillbox { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
/* CR-0312 (feedback): the request button is always pushed to the far right of the head row. */
.ps-seats-el .ps-seats-el__request { border-radius: 25px !important; margin-left: auto; }
.ps-seats-el__request:disabled,
.ps-seats-el__request[disabled] { opacity: .5 !important; cursor: not-allowed !important; box-shadow: none !important; }
.ps-seats-el__biz { margin: 0; text-align: center; font-size: 13px; font-weight: 700; color: #1d2327; }
.ps-seats-el__tiers { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.ps-seats-el__tierpill { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; padding: 5px 12px; border-radius: 14px; background: #f0f0f1; border: 1px solid transparent; line-height: 1.2; }
/* CR-0312 (feedback): a coloured pill keeps its inline background + auto-contrast text (label/seats inherit it). */
.ps-seats-el__tierpill.has-colour .ps-seats-el__tierpill-label,
.ps-seats-el__tierpill.has-colour .ps-seats-el__tierpill-seats { color: inherit; }
/* The current tier is boxed — a dark ring that reads over any pill colour (falls back to the blue box when uncoloured). */
.ps-seats-el__tierpill.is-current { background: #e5eefc; border-color: #2158b0; }
.ps-seats-el__tierpill.is-current.has-colour { box-shadow: 0 0 0 2px #1d2327; }
.ps-seats-el__tierpill-label { font-size: 13px; font-weight: 700; color: #1d2327; }
.ps-seats-el__tierpill-seats { font-size: 11px; color: #556; }
/* CR-0312 (feedback): the slot-sum headline sits BELOW the element name (keeps the card the same height as the tier card). */
.ps-seats-el__headline { display: block; margin: 2px 0 0; font-size: 13px; font-weight: 700; color: #1d2327; }
/* A locked slots card dims its pills + headline too (matching the dimmed head + greyed button). */
.ps-programme-el.is-locked .ps-seats-el__pillbox { opacity: .6; }
.ps-seats-el__state { padding: 8px 14px 12px; font-size: 13px; color: #556; }
.ps-seats-el--pending .ps-seats-el__state { color: #7a5b00; }
.ps-seats-el__pop { position: absolute; right: 14px; top: calc(100% - 6px); z-index: 20; box-sizing: border-box; display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: 320px; max-width: calc(100vw - 32px); padding: 12px 14px; background: #fff; border: 1px solid #c3c4c7; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,.16); }
.ps-seats-el__pop *, .ps-seats-el__pop *::before, .ps-seats-el__pop *::after { box-sizing: border-box; }
.ps-seats-el__pop[hidden] { display: none; }
.ps-seats-el__pop-label { display: flex; flex-direction: column; align-items: stretch; gap: 4px; font-size: 13px; }
.ps-seats-el__pop-label input { display: block; width: 100%; max-width: 100%; }
.ps-seats-el__cost { margin: 0; font-size: 12px; line-height: 1.4; color: #556; }
.ps-seats-el__ack-label { display: flex; align-items: flex-start; gap: 6px; font-size: 12px; color: #1d2327; }
.ps-seats-el__ack-label input { margin-top: 2px; }
.ps-seats-el__actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ps-seats-el__submit, .ps-seats-el__cancel { border-radius: 25px; }
.ps-seats-el__submit:disabled { cursor: not-allowed; opacity: .6; }
.ps-seats-el__msg { font-size: 12px; color: #556; min-width: 60px; }
@media (max-width: 640px) {
	.ps-seats-el__pop { left: 8px; right: 8px; width: auto; max-width: none; }
	/* CR-0312 (feedback): on mobile the pill box drops below the name as a unit; the button follows on its own row but
	   stays hard-right (overriding the generic mobile left-align rule below), so "button always on the right" holds. */
	.ps-seats-el__name-wrap { flex: 1 1 100%; }
	.ps-seats-el__pillbox { flex: 1 1 100%; align-items: flex-start; }
	.ps-seats-el__tiers { justify-content: flex-start; }
	.ps-seats-el .ps-seats-el__request,
	.ps-seats-el .ps-programme-el__lockwrap { margin-left: auto !important; order: 0; }
}
/* CR-0300: responsive member view ([ps_programme]) for phones/tablets — the card face is a no-wrap flex on desktop,
   so on a narrow screen let it wrap (thumb + status + name stay on line 1; the action/toggle drop to line 2, still
   right-aligned via their margin-left:auto), shrink the thumbnail, reduce the child indent, and keep the tier meta +
   tier-picker popover inside the viewport instead of overflowing off the right edge. */
@media (max-width: 600px) {
	.ps-programme { margin: 1em 0; }
	.ps-programme-el__head { flex-wrap: wrap; padding: 10px 12px; gap: 8px 10px; }
	/* A 60% basis for the name keeps thumb+status+name filling line 1, so any action/toggle wraps below. */
	.ps-programme-el__name-wrap { flex: 1 1 60%; }
	.ps-programme-el__name { font-size: 1rem; }
	/* CR-0312 (feedback): consistency — when the action + optional pill wrap below the content, keep the button
	   LEFT-aligned (like the majority) with the pill to its RIGHT. DOM order is pill-then-action, so `order` puts the
	   button first; clearing any auto margin left-aligns it. (Cards with their own mobile order — e.g. the tier
	   element's `.ps-tier-el__request` order:3 — are more specific and keep their placement.) */
	.ps-programme-el__action { order: 5; margin-left: 0 !important; }
	.ps-programme-el__pill { order: 6; }
	.ps-programme-el__thumb { width: 72px; height: 40px; }
	.ps-programme-el--child { margin-left: 12px; }
	.ps-pm-el--child { padding-left: 1em; }
	/* Detail body / member text: tighter side padding to match the smaller head. */
	.ps-programme-el__body,
	.ps-programme-el__text { padding-left: 12px; padding-right: 12px; }

	/* CR-0301: Tier-request element — the head packs name + org/tier/type meta + the Request button on ONE flex line,
	   which on a phone squeezes each to a single vertical character column. Force the meta onto its OWN full-width row
	   (`flex: 0 0 100%`, not just `width` — with flex-wrap that guarantees a line break); the name then keeps the whole
	   first line and the Request button + info toggle drop below it with room to render horizontally. */
	.ps-tier-el .ps-programme-el__head { flex-wrap: wrap; row-gap: 10px; }
	.ps-tier-el .ps-programme-el__name-wrap { flex: 1 1 auto; }
	/* CR-0302: keep the (i) info toggle on the name's row at the top-right — same place as every other card — by
	   ordering it before the (full-width) meta and Request rows, which drop beneath. */
	/* CR-0308: the (i) toggle now lives in the icon slot (right after the image, DOM order) — no reorder needed. */
	.ps-tier-el__meta { order: 2; flex: 0 0 100%; margin-left: 0; justify-content: flex-start; flex-wrap: wrap; gap: 8px 12px; }
	.ps-tier-el__orgpill { align-items: flex-start; text-align: left; }
	.ps-tier-el__org { max-width: 100%; white-space: normal; }
	.ps-tier-el .ps-tier-el__request { order: 3; margin-left: 0 !important; }
	/* The tier-picker popover spans the card width (its controls already wrap) instead of running off-screen. On a phone
	   let left+right define the width (clear the desktop fixed width + cap, else `width` would win and `right` be ignored). */
	.ps-tier-el__pop { left: 8px; right: 8px; width: auto; max-width: none; }
	.ps-tier-el__pop select { max-width: 100%; }
}

/* CR-0322: [ps_member_orgs] — a member's organisations in a multi-org membership, with a publish/draft dot and
   Edit / View / Preview actions (the Edit/Preview panels wrap the Organisation Directory's own shortcodes). */
.ps-member-orgs__list { list-style: none; margin: 0; padding: 0; }
.ps-member-orgs__item { border: 1px solid rgba(0, 0, 0, .12); border-radius: 6px; padding: .6rem .8rem; margin: 0 0 .6rem; }
.ps-member-orgs__head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.ps-member-orgs__logo { flex: 0 0 auto; display: inline-flex; align-items: center; }
.ps-member-orgs__logo-img { max-height: 36px; max-width: 90px; width: auto; height: auto; object-fit: contain; display: block; }
.ps-member-orgs__dot { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%; flex: 0 0 auto; }
.ps-member-orgs__dot--published { background: #1a7f37; }
.ps-member-orgs__dot--draft { background: #cf222e; }
.ps-member-orgs__membership { color: #555; font-size: .85em; }
.ps-member-orgs__org { font-weight: 700; }
.ps-member-orgs__status { display: inline-flex; align-items: center; gap: .35rem; color: #555; font-size: .85em; }
.ps-member-orgs__actions { margin-left: auto; display: flex; gap: .4rem; flex-wrap: wrap; }
/* CR-0322 (feedback): pill-radius action buttons. */
.ps-member-orgs__action { border-radius: 25px; }
.ps-member-orgs__panel { margin-top: .7rem; padding-top: .7rem; border-top: 1px solid rgba(0, 0, 0, .1); }
.ps-member-orgs__empty, .ps-member-orgs__notice { color: #555; }
@media ( max-width: 600px ) {
	.ps-member-orgs__actions { margin-left: 0; width: 100%; }
}

/* CR-0327 Inc 3: the per-member "Receive admin emails" opt-out column (member-manage + owner-manage consoles). A
   member with no flagged role shows a muted em-dash — "not applicable", never an unticked box (which would read as
   "switched off"). A disabled checkbox means this viewer may not flip that row. */
.ps-admin-email, .ps-owner__admin-email { text-align: center; white-space: nowrap; }
.ps-na, .ps-owner__na { color: #64748b; cursor: help; }
.ps-admin-email-toggle[disabled], .ps-owner__admin-email-toggle[disabled] { cursor: not-allowed; opacity: .55; }

/* CR-0339 — the Checklist element. One card holding a heading, an optional summary and the to-do list. Ticks are
   DISPLAY ONLY (driven by tag conditions, never clickable), so the box is a plain span rather than a real checkbox —
   a disabled <input type=checkbox> would invite clicks and read as "broken" to a keyboard user. */
.ps-programme-el--checklist { display: block; padding: .9rem 1rem; }
.ps-programme-el--checklist .ps-chk-head { margin-bottom: .25rem; }
.ps-chk-summary { margin: 0 0 .6rem; color: #475569; font-size: .9375rem; }
.ps-chk-summary p { margin: 0 0 .4rem; }
.ps-chk-summary p:last-child { margin-bottom: 0; }
.ps-chk-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.ps-chk-row { display: flex; align-items: center; gap: .55rem; line-height: 1.35; }
/* A to-do carrying details gets the native tooltip, so hint that hovering does something. */
.ps-chk-row[title] { cursor: help; }
.ps-chk-box {
	flex: 0 0 auto; width: 1.05rem; height: 1.05rem; border: 1px solid #cbd5e1; border-radius: 3px;
	background: #f8fafc; display: inline-flex; align-items: center; justify-content: center;
	font-size: .8rem; line-height: 1; color: #fff;
}
.ps-chk-row.is-ticked .ps-chk-box { background: #16a34a; border-color: #16a34a; }
.ps-chk-row.is-ticked .ps-chk-text { color: #16a34a; }
.ps-chk-text { color: #475569; }
/* CR-0339 (feedback) — the optional per-to-do link icon. Only rendered while the item is unticked, so it needs no
   "hidden when done" rule; the colour just has to read as a link beside the muted to-do text. */
.ps-chk-link { display: inline-flex; align-items: center; color: #2158b0; margin-left: .35rem; text-decoration: none; }
.ps-chk-link:hover, .ps-chk-link:focus-visible { color: #17407f; }

/* CR-0383: the application-form configuration notice. It had NO rule at all — `.ps-notice` was in the markup and
   nowhere in this stylesheet — so it rendered as ordinary body text and was read past for weeks while applications
   fanned out to three memberships. A warning indistinguishable from prose is not a warning.

   Two severities, because they ask for different things: a WARNING describes real behaviour the operator may not
   want (light red, as asked), an ERROR names something outright broken (deeper red, heavier rule). Both are
   manager-only, so no applicant ever sees them. */
.ps-application-form-notice {
	margin: 0 0 1rem;
	padding: .75rem 1rem;
	border-radius: 4px;
	border-left: 4px solid currentColor;
	font-size: .95em;
	line-height: 1.5;
}
.ps-application-form-notice--warning {
	background: #fdeaea;
	border-left-color: #d63638;
	color: #8a1f21;
}
.ps-application-form-notice--error {
	background: #f8d7da;
	border-left-color: #a00;
	color: #7a1418;
	font-weight: 600;
}

/* BG0245: the owner console members table — the Email title fits (th carries ps-col-email now, so the shrink-to-
   fit + nowrap rules above finally match this header), Email and Roles centre, and Actions gives its slack back
   by shrinking to its buttons. All inside the existing horizontal-scroll + sticky-actions mobile behaviour. */
.ps-owner__members th.ps-col-email,
.ps-owner__members td.ps-owner__email { text-align: center; }
.ps-owner__members th.ps-owner__roles-head,
.ps-owner__members td.ps-owner__roles { text-align: center; }
.ps-owner__members th.ps-owner__roles-head .ps-owner__sort,
.ps-owner__members th.ps-col-email .ps-owner__sort { margin: 0 auto; }
.ps-owner__members th.ps-col-actions,
.ps-owner__members td.ps-owner__actions { width: 1%; white-space: nowrap; }
@media (max-width: 380px) {
	/* Parity with the manage-table rule above: stacked full-width action buttons on very narrow screens. */
	.ps-owner__members td.ps-owner__actions .ps-btn { display: block; width: 100%; margin: 4px 0 0; text-align: center; }
}

/* ─── CR-0449: the Programme-duration timeline ─────────────────────────────────────────────────────────────────
   One bar tells the whole story: dates anchored at the ends, the elapsed span filled, a today-marker carrying the
   remaining time. Expired turns the fill red with its status line; open-ended fades the fill into an ∞ end. */
.ps-programme-el--programme_duration { padding: 1rem 1.1rem; }
.ps-programme-el--programme_duration .ps-dur-head { margin-bottom: .25rem; }
.ps-dur__summary { margin: 0 0 .6rem; color: #475569; font-size: .9375rem; }
.ps-dur { margin-top: .35rem; }
.ps-dur__dates { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .4rem; }
.ps-dur__date { font-size: .8125rem; font-weight: 600; color: #334155; letter-spacing: .01em; }
.ps-dur__date--open { font-size: 1rem; color: #94a3b8; line-height: 1; }
.ps-dur__bar { position: relative; height: 10px; border-radius: 999px; background: #e2e8f0; overflow: visible; }
.ps-dur__fill { display: block; height: 100%; border-radius: 999px;
	background: linear-gradient(90deg, #2563eb, #3b82f6); transition: width .4s ease; max-width: 100%; }
.ps-dur__bar.is-open-ended .ps-dur__fill {
	background: linear-gradient(90deg, #2563eb 0%, #3b82f6 55%, rgba(59, 130, 246, 0) 100%); }
.ps-dur__bar.is-expired .ps-dur__fill { background: linear-gradient(90deg, #dc2626, #ef4444); }
.ps-dur__marker { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 16px; height: 16px;
	border-radius: 50%; background: #fff; border: 3px solid #2563eb; box-shadow: 0 1px 3px rgba(15, 23, 42, .25); }
.ps-dur__today { position: absolute; bottom: calc(100% + 7px); left: 50%; transform: translateX(-50%);
	white-space: nowrap; background: #1e293b; color: #fff; font-size: .75rem; font-weight: 600;
	padding: .2rem .55rem; border-radius: .375rem; }
.ps-dur__today::after { content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
	border: 5px solid transparent; border-top-color: #1e293b; }
/* Keep the tooltip on-canvas at the extremes of the bar. */
.ps-dur__marker[style*="left:9"] .ps-dur__today,
.ps-dur__marker[style*="left:8"] .ps-dur__today { left: auto; right: -8px; transform: none; }
.ps-dur__marker[style*="left:0"] .ps-dur__today,
.ps-dur__marker[style*="left:1."] .ps-dur__today { left: -8px; transform: none; }
.ps-dur__bar { margin-top: 1.9rem; } /* room for the marker tooltip above the bar */
.ps-programme-el--programme_duration .ps-dur__dates { margin-bottom: 0; }
.ps-dur__status { margin: .55rem 0 0; font-size: .8125rem; font-weight: 600; color: #475569; }
.ps-dur__status--expired { color: #b91c1c; }
.ps-dur__note { margin: .3rem 0 0; font-size: .875rem; color: #64748b; font-style: italic; }
@media (max-width: 480px) {
	.ps-dur__today { font-size: .6875rem; padding: .15rem .4rem; }
	.ps-dur__date { font-size: .75rem; }
}

/* ── CR-0454: the member-facing compliance surfaces ────────────────────────── */

/* The member's own record of what they have agreed to. */
.ps-consents__list { list-style: none; margin: 0; padding: 0; }
.ps-consent {
	display: flex; flex-wrap: wrap; gap: .75em; align-items: flex-start; justify-content: space-between;
	padding: .75em 0; border-bottom: 1px solid rgba(0, 0, 0, .08);
}
.ps-consent:last-child { border-bottom: 0; }
.ps-consent__main { display: flex; flex-direction: column; gap: .15em; min-width: 0; flex: 1 1 20em; }
.ps-consent__name { font-weight: 600; }
.ps-consent__state { font-weight: 600; }
.ps-consent--granted .ps-consent__state { color: #1a7a1a; }
.ps-consent--superseded .ps-consent__state,
.ps-consent--none .ps-consent__state { color: #a35a00; }
.ps-consent--withdrawn .ps-consent__state,
.ps-consent--declined .ps-consent__state { color: #646970; }
.ps-consent__why, .ps-consent__when { font-size: .9em; color: #646970; }
.ps-consent__actions { flex: 0 0 auto; }
.ps-consents__notice { padding: .6em .8em; background: #f0f6fc; border-left: 3px solid #72aee6; }

/* An agreement rendered on a page. */
/* CR-0457 D3: the statement is a bordered, titled box so it is obvious where the agreement begins and
   ends. It sits inside a form among other fields; without a boundary the text ran into its surroundings
   and the reader could not tell what they were agreeing to. */
.ps-agreement--form {
	border: 1px solid #c3c4c7;
	border-left: 4px solid #2271b1;
	border-radius: 3px;
	padding: 1em 1.25em;
	margin: 1em 0;
	background: #fff;
}
.ps-agreement__title { margin: 0 0 .15em; font-size: 1.05em; line-height: 1.3; }
/* Version and date sit under the title, smaller — they qualify the agreement, they are not part of it. */
.ps-agreement__meta { font-size: .85em; color: #646970; margin: 0 0 .75em; }
.ps-agreement__body > *:last-child { margin-bottom: 0; }
.ps-agreement__superseded { padding: .6em .8em; background: #fcf3e6; border-left: 3px solid #dba617; }
.ps-agreement__history { margin-top: .5em; font-size: .9em; }
/* A quoted agreement, baked in at publish. Set apart so a reader can see where the quotation starts and stops —
   otherwise Schedule 1 reads as though the quoted wording were this document's own. */
.ps-agreement__quote {
	margin: 1em 0; padding: .75em 1em;
	border-left: 3px solid rgba(0, 0, 0, .15); background: rgba(0, 0, 0, .02);
}

/* Accept / Decline on a catch-up link.
   Art 7(3): withdrawal must be AS EASY as giving, so these two are laid out side by side and forced to an identical
   box — the CR-0134 lesson that two adjacent buttons compute different heights unless an explicit equal height is
   set on both. Stacked block-level forms (which is what they were before this rule existed) put one above the
   other, and the top one reads as the intended answer. Same class, same rule, no `button-primary` on either. */
.ps-agreement__respond { display: flex; flex-wrap: wrap; gap: .6em; margin-top: 1em; }
.ps-agreement__respond-form { margin: 0; }
.ps-agreement__respond-btn {
	box-sizing: border-box; height: 40px; min-height: 40px; min-width: 12em;
	display: inline-flex; align-items: center; justify-content: center;
	padding: 0 1.2em; font-size: 1em; line-height: 1;
}
.ps-agreement__done { padding: .6em .8em; background: #edfaef; border-left: 3px solid #4ab866; }
.ps-agreement__missing { padding: .6em .8em; background: #fcf0f1; border-left: 3px solid #d63638; }
/* CR-0467: statement presentation on forms. The text is on the page in every mode; only its footprint changes. */
.ps-agreement__body.is-scroll { max-height: 22rem; overflow: auto; padding: .75rem 1rem; border: 1px solid #dcdcde; border-radius: 4px; background: #fff; }
.ps-agreement__scroll { position: relative; }
.ps-agreement__expand { position: absolute; top: .4rem; right: 1.1rem; z-index: 1; width: 1.7rem; height: 1.7rem; padding: 0; line-height: 1.5rem; font-size: 1rem; text-align: center; color: #50575e; background: #fff; border: 1px solid #dcdcde; border-radius: 4px; cursor: pointer; }
.ps-agreement__expand:hover, .ps-agreement__expand:focus-visible { color: #1d2327; border-color: #8c8f94; }
.ps-agreement__scroll .ps-agreement__body.is-scroll { padding-right: 2.6rem; }
.ps-agreement__scroll.is-expanded .ps-agreement__body.is-scroll { max-height: none; overflow: visible; }
.ps-agreement__collapse > summary { cursor: pointer; font-weight: 600; margin: .25rem 0 .5rem; }
.ps-agreement__body.is-collapsed { padding: .5rem 0; }
.ps-agreement__open { margin: 0 0 .5rem; font-size: .95em; }
/* A quoted document brings its own headings; inside the statement they must not shout in the theme's H1. */
.ps-agreement__body h1, .ps-agreement__body h2 { font-size: 1.15em; font-family: inherit; font-weight: 600; margin: 1em 0 .35em; line-height: 1.3; }
.ps-agreement__body h3, .ps-agreement__body h4 { font-size: 1.02em; font-family: inherit; font-weight: 600; margin: .9em 0 .3em; }
.ps-agreement__body p, .ps-agreement__body li { font-size: .95em; line-height: 1.5; }
